Compare commits
28 commits
main
...
showplayer
Author | SHA1 | Date | |
---|---|---|---|
|
9c559e8a8f | ||
|
e68b46f3b7 | ||
|
6da193c50d | ||
|
f665ccfd7d | ||
|
f4bf71dbcf | ||
|
f6eb15f13c | ||
|
11bd76a458 | ||
|
8716004c5e | ||
|
eed68d1817 | ||
|
46b7624fb5 | ||
|
b4988a1307 | ||
|
aa713fd9be | ||
|
d35b166ce5 | ||
|
14a51c88e9 | ||
|
307d9c4d43 | ||
|
e39d885f6f | ||
|
6056778856 | ||
|
0795157d5f | ||
|
86e866c996 | ||
|
d9e755cd32 | ||
|
14a8aab0a4 | ||
|
84702c5e44 | ||
|
3b98be8b14 | ||
|
bd9b07f000 | ||
|
333d7c7b49 | ||
|
52b44a4d7c | ||
|
647b75f168 | ||
|
9c97f20470 |
2
.gitignore
vendored
|
@ -44,3 +44,5 @@ log/**
|
||||||
|
|
||||||
*~
|
*~
|
||||||
*.autosave
|
*.autosave
|
||||||
|
|
||||||
|
*.vscode*
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<lmsAudio ui="1" layersNumber="4" path="../media/sound" >
|
|
||||||
<audioDevice devicesNumber="2" id0="3" id1="4"/>
|
|
||||||
<layer id="0" dmx="1" universe="1" audioDevice="0" />
|
|
||||||
<layer id="1" dmx="17" universe="1" audioDevice="0" />
|
|
||||||
<layer id="2" dmx="33" universe="1" audioDevice="1" />
|
|
||||||
<layer id="3" dmx="49" universe="1" audioDevice="1"/>
|
|
||||||
</lmsAudio>
|
|
8
docs/lms-audio.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<lmsAudio ui="1" dmxActive="0" showPlayerActive="1" layersNumber="4" path="../media/sound" >
|
||||||
|
<audioDevice devicesNumber="2" id0="4" id1="3"/>
|
||||||
|
<layer id="0" dmx="1" universe="1" audioDevice="0" />
|
||||||
|
<layer id="1" dmx="26" universe="1" audioDevice="0" />
|
||||||
|
<layer id="2" dmx="51" universe="1" audioDevice="1" />
|
||||||
|
<layer id="3" dmx="76" universe="1" audioDevice="1"/>
|
||||||
|
</lmsAudio>
|
|
@ -34,7 +34,6 @@ v 0.3.0
|
||||||
- Rose noise and sine generator.
|
- Rose noise and sine generator.
|
||||||
- Logs, verbosity, timestamp.
|
- Logs, verbosity, timestamp.
|
||||||
- New play mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH
|
- New play mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH
|
||||||
- SettingsDialog.
|
|
||||||
- Load/save conf file.
|
- Load/save conf file.
|
||||||
- ¿Exit Point? is it needed?
|
- ¿Exit Point? is it needed?
|
||||||
- Hardening: check return errors, try/catch exceptions, i'm too happy....
|
- Hardening: check return errors, try/catch exceptions, i'm too happy....
|
||||||
|
@ -42,3 +41,9 @@ v 0.3.0
|
||||||
- ampliar writer para recibir un número n de entradas y escribirlas cada una en un buffer
|
- ampliar writer para recibir un número n de entradas y escribirlas cada una en un buffer
|
||||||
- aislar miniaudio del callback dmx tal como hemos hecho con la Ui, al menos las operaciones lentas como cargar medios.
|
- aislar miniaudio del callback dmx tal como hemos hecho con la Ui, al menos las operaciones lentas como cargar medios.
|
||||||
- en load media usar un fence para actualizar mediaLoaded.
|
- en load media usar un fence para actualizar mediaLoaded.
|
||||||
|
- Video
|
||||||
|
|
||||||
|
v 0.2.1 showplayer
|
||||||
|
|
||||||
|
- SettingsDialog, configuración gráfica.
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,16 @@ TEMPLATE = app
|
||||||
TARGET = libremediaserver-audio
|
TARGET = libremediaserver-audio
|
||||||
QT += webkitwidgets widgets
|
QT += webkitwidgets widgets
|
||||||
HEADERS += src/libremediaserver-audio.h \
|
HEADERS += src/libremediaserver-audio.h \
|
||||||
|
src/cuetrackwidget.h \
|
||||||
|
src/editcuetrackwidget.h \
|
||||||
|
src/cuetracklistwidget.h \
|
||||||
|
src/showplayer.h \
|
||||||
src/clickabledoublespinbox.h \
|
src/clickabledoublespinbox.h \
|
||||||
src/clickablelabel.h \
|
src/clickablelabel.h \
|
||||||
src/clickableslider.h \
|
src/clickableslider.h \
|
||||||
src/dmxwidget.h \
|
src/dmxwidget.h \
|
||||||
src/filterbankwidget.h \
|
src/filterbankwidget.h \
|
||||||
src/libremediaserver-audio-gui.h \
|
src/libremediaserver-audio-ui.h \
|
||||||
src/ma_writer_node.h \
|
src/ma_writer_node.h \
|
||||||
src/main.h \
|
src/main.h \
|
||||||
src/medialibrary.h \
|
src/medialibrary.h \
|
||||||
|
@ -20,14 +24,20 @@ HEADERS += src/libremediaserver-audio.h \
|
||||||
src/audiowidget.h \
|
src/audiowidget.h \
|
||||||
src/defines.h \
|
src/defines.h \
|
||||||
src/settings.h \
|
src/settings.h \
|
||||||
src/slidergroup.h
|
src/slidergroup.h \
|
||||||
|
src/dialgroup.h \
|
||||||
|
src/audiofade.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
|
src/cuetrackwidget.cpp \
|
||||||
|
src/editcuetrackwidget.cpp \
|
||||||
|
src/cuetracklistwidget.cpp \
|
||||||
|
src/showplayer.cpp \
|
||||||
src/clickabledoublespinbox.cpp \
|
src/clickabledoublespinbox.cpp \
|
||||||
src/clickablelabel.cpp \
|
src/clickablelabel.cpp \
|
||||||
src/clickableslider.cpp \
|
src/clickableslider.cpp \
|
||||||
src/dmxwidget.cpp \
|
src/dmxwidget.cpp \
|
||||||
src/filterbankwidget.cpp \
|
src/filterbankwidget.cpp \
|
||||||
src/libremediaserver-audio-gui.cpp \
|
src/libremediaserver-audio-ui.cpp \
|
||||||
src/libremediaserver-audio.cpp \
|
src/libremediaserver-audio.cpp \
|
||||||
src/medialibrary.cpp \
|
src/medialibrary.cpp \
|
||||||
src/miniaudio.c \
|
src/miniaudio.c \
|
||||||
|
@ -37,17 +47,22 @@ SOURCES += src/main.cpp \
|
||||||
src/audiolayerwidget.cpp \
|
src/audiolayerwidget.cpp \
|
||||||
src/audiowidget.cpp \
|
src/audiowidget.cpp \
|
||||||
src/settings.cpp \
|
src/settings.cpp \
|
||||||
src/slidergroup.cpp
|
src/slidergroup.cpp \
|
||||||
FORMS += src/libremediaserver-audio-gui.ui
|
src/dialgroup.cpp
|
||||||
|
FORMS += \
|
||||||
|
src/cuetrackwidget.ui \
|
||||||
|
src/showplayer.ui \
|
||||||
|
src/libremediaserver-audio-ui.ui
|
||||||
CCFLAG += -msse2 -mavx2
|
CCFLAG += -msse2 -mavx2
|
||||||
QMAKE_CXXFLAGS += $$(CXXFLAG)
|
QMAKE_CXXFLAGS += $$(CXXFLAG)
|
||||||
QMAKE_CFLAGS += $$(CCFLAG)
|
QMAKE_CFLAGS += $$(CCFLAG)
|
||||||
QMAKE_LFLAGS += $$(LDFLAG)
|
QMAKE_LFLAGS += $$(LDFLAG)
|
||||||
LIBS += -lola -lolacommon -ldl -lpthread -lm
|
LIBS += -lola -lolacommon -ldl -lpthread -lm
|
||||||
# -lcitp
|
|
||||||
OTHER_FILES += \
|
OTHER_FILES += \
|
||||||
LICENSE.txt \
|
LICENSE.txt \
|
||||||
docs/compiling.txt \
|
docs/compiling.txt \
|
||||||
docs/changelog.txt \
|
docs/changelog.txt \
|
||||||
docs/lms-audio.xlm \
|
docs/lms-audio.xlm \
|
||||||
docs/roadmap.txt
|
docs/roadmap.txt
|
||||||
|
RESOURCES += \
|
||||||
|
lms-resources.qrc
|
||||||
|
|
16
lms-resources.qrc
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/buttons">
|
||||||
|
<file>resources/copy_button.png</file>
|
||||||
|
<file>resources/cut_button.png</file>
|
||||||
|
<file>resources/delete_button.png</file>
|
||||||
|
<file>resources/edit_button.png</file>
|
||||||
|
<file>resources/load_button.png</file>
|
||||||
|
<file>resources/new_button.png</file>
|
||||||
|
<file>resources/paste_button.png</file>
|
||||||
|
<file>resources/save_button.png</file>
|
||||||
|
<file>resources/icon.png</file>
|
||||||
|
<file>resources/panic_button.jpg</file>
|
||||||
|
<file>resources/go_button.jpeg</file>
|
||||||
|
<file>resources/restore_button.jpg</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
BIN
resources/copy_button.png
Normal file
After Width: | Height: | Size: 871 B |
BIN
resources/cut_button.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
resources/delete_button.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
resources/edit_button.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
resources/icon.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
resources/load_button.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
resources/new_button.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
resources/panic_button.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
resources/paste_button.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
resources/restore_button.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
resources/save_button.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
23
src/.qmake.stash
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
QMAKE_CXX.QT_COMPILER_STDCXX = 201703L
|
||||||
|
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 11
|
||||||
|
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 4
|
||||||
|
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0
|
||||||
|
QMAKE_CXX.COMPILER_MACROS = \
|
||||||
|
QT_COMPILER_STDCXX \
|
||||||
|
QMAKE_GCC_MAJOR_VERSION \
|
||||||
|
QMAKE_GCC_MINOR_VERSION \
|
||||||
|
QMAKE_GCC_PATCH_VERSION
|
||||||
|
QMAKE_CXX.INCDIRS = \
|
||||||
|
/usr/include/c++/11 \
|
||||||
|
/usr/include/x86_64-linux-gnu/c++/11 \
|
||||||
|
/usr/include/c++/11/backward \
|
||||||
|
/usr/lib/gcc/x86_64-linux-gnu/11/include \
|
||||||
|
/usr/local/include \
|
||||||
|
/usr/include/x86_64-linux-gnu \
|
||||||
|
/usr/include
|
||||||
|
QMAKE_CXX.LIBDIRS = \
|
||||||
|
/usr/lib/gcc/x86_64-linux-gnu/11 \
|
||||||
|
/usr/lib/x86_64-linux-gnu \
|
||||||
|
/usr/lib \
|
||||||
|
/lib/x86_64-linux-gnu \
|
||||||
|
/lib
|
|
@ -275,10 +275,10 @@ void AudioLayerWidget::setMediaFile(QString file)
|
||||||
int size = list.size();
|
int size = list.size();
|
||||||
if (size >= 2) {
|
if (size >= 2) {
|
||||||
QString tmp = list.at(size - 2);
|
QString tmp = list.at(size - 2);
|
||||||
tmp.truncate(60);
|
tmp.truncate(64);
|
||||||
m_folderValue->setText(tmp);
|
m_folderValue->setText(tmp);
|
||||||
tmp = list.at(size - 1);
|
tmp = list.at(size - 1);
|
||||||
tmp.truncate(40);
|
tmp.truncate(64);
|
||||||
m_fileValue->setText(tmp);
|
m_fileValue->setText(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ public:
|
||||||
explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0);
|
explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0);
|
||||||
~AudioLayerWidget();
|
~AudioLayerWidget();
|
||||||
|
|
||||||
// From OLA -> LibreMediaServer -> AudioWidget
|
|
||||||
void setMediaFile(QString file);
|
void setMediaFile(QString file);
|
||||||
void setDuration(float dur);
|
void setDuration(float dur);
|
||||||
void setCurrentTime(float progress);
|
void setCurrentTime(float progress);
|
||||||
|
|
|
@ -5,13 +5,5 @@
|
||||||
ClickableDoubleSpinBox::ClickableDoubleSpinBox(QWidget *parent)
|
ClickableDoubleSpinBox::ClickableDoubleSpinBox(QWidget *parent)
|
||||||
: QDoubleSpinBox(parent)
|
: QDoubleSpinBox(parent)
|
||||||
{
|
{
|
||||||
setFocusPolicy(Qt::NoFocus);
|
|
||||||
setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
||||||
setValue(-1);
|
|
||||||
setDecimals(1);
|
|
||||||
setAlignment(Qt::AlignHCenter);
|
|
||||||
setContentsMargins(0, 0, 0, 0);
|
|
||||||
setMaximumWidth(66);
|
|
||||||
setMinimumWidth(25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,20 @@ class ClickableDoubleSpinBox : public QDoubleSpinBox
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
bool active = false;
|
||||||
|
|
||||||
explicit ClickableDoubleSpinBox(QWidget *parent = nullptr);
|
explicit ClickableDoubleSpinBox(QWidget *parent = nullptr);
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent ( QMouseEvent * event ) {
|
void mousePressEvent ( QMouseEvent * event ) {
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
emit click();
|
emit click();
|
||||||
|
active = true;
|
||||||
|
//this->setBackgroundRole(QPalette::BrightText);
|
||||||
|
|
||||||
|
} else if (event->button() == Qt::RightButton) {
|
||||||
|
emit click();
|
||||||
|
active = false;
|
||||||
|
//this->setBackgroundRole(QPalette::Shadow);
|
||||||
}
|
}
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
605
src/cuetracklistwidget.cpp
Normal file
|
@ -0,0 +1,605 @@
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <QTableWidgetItem>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include "cuetracklistwidget.h"
|
||||||
|
#include "editcuetrackwidget.h"
|
||||||
|
|
||||||
|
CueTrackListWidget::CueTrackListWidget(QWidget *parent)
|
||||||
|
{
|
||||||
|
layout = new QVBoxLayout(this);
|
||||||
|
tableWidget = new QTableWidget();
|
||||||
|
tableWidget->setSortingEnabled(false);
|
||||||
|
layout->addWidget(tableWidget);
|
||||||
|
setLayout(layout);
|
||||||
|
tableWidget->installEventFilter(parent);
|
||||||
|
QShortcut *shortcut_up = new QShortcut(QKeySequence("Up"), parent);
|
||||||
|
QObject::connect(shortcut_up, SIGNAL(activated()), this , SLOT(key_up()));
|
||||||
|
QShortcut *shortcut_down = new QShortcut(QKeySequence("Down"), parent);
|
||||||
|
QObject::connect(shortcut_down, SIGNAL(activated()), this, SLOT(key_down()));
|
||||||
|
QShortcut *shortcut_copy = new QShortcut(QKeySequence("Ctrl+C"), parent);
|
||||||
|
QObject::connect(shortcut_copy, SIGNAL(activated()), this, SLOT(copyCueTrack()));
|
||||||
|
QShortcut *shortcut_cut = new QShortcut(QKeySequence("Ctrl+X"), parent);
|
||||||
|
QObject::connect(shortcut_cut, SIGNAL(activated()), this, SLOT(cutCueTrack()));
|
||||||
|
QShortcut *shortcut_paste = new QShortcut(QKeySequence("Ctrl+V"), parent);
|
||||||
|
QObject::connect(shortcut_paste, SIGNAL(activated()), this, SLOT(pasteCueTrack()));
|
||||||
|
QShortcut *shortcut_delete = new QShortcut(QKeySequence("Delete"), parent);
|
||||||
|
QObject::connect(shortcut_delete, SIGNAL(activated()), this, SLOT(deleteCueTrack()));
|
||||||
|
QShortcut *shortcut_insert = new QShortcut(QKeySequence("Insert"), parent);
|
||||||
|
QObject::connect(shortcut_insert, SIGNAL(activated()), this, SLOT(createNewCueTrack()));
|
||||||
|
QShortcut *shortcut_edit = new QShortcut(QKeySequence("e"), parent);
|
||||||
|
QObject::connect(shortcut_edit, SIGNAL(activated()), this, SLOT(editCueTrack()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::addCueTrack(CueTrack* cue) {
|
||||||
|
cueTracks.push_back(cue);
|
||||||
|
displayCueTrackInTable(cue, -1);
|
||||||
|
m_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::removeCueTrack(int index) {
|
||||||
|
if (index >= m_size) return;
|
||||||
|
cueTracks.erase(cueTracks.begin() + index);
|
||||||
|
tableWidget->removeRow(index);
|
||||||
|
m_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
CueTrack* CueTrackListWidget::getTrackAtIndex(int index) {
|
||||||
|
if (index < m_size) {
|
||||||
|
return cueTracks.at(index);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CueTrack* CueTrackListWidget::getSelectedTrack(bool advance) {
|
||||||
|
CueTrack* track = getTrackAtIndex(selectedIndex);
|
||||||
|
if (advance)
|
||||||
|
key_down();
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::key_up() {
|
||||||
|
|
||||||
|
if (m_size > 0 && selectedIndex > 0) {
|
||||||
|
updateSelectedCueTrack(false);
|
||||||
|
selectedIndex--;
|
||||||
|
updateSelectedCueTrack(true);
|
||||||
|
tableWidget->scrollToItem(tableWidget->item(selectedIndex, 0));
|
||||||
|
}
|
||||||
|
emit changeSelectedIndex(selectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::key_down() {
|
||||||
|
if (selectedIndex < m_size - 1 && m_size > 0) {
|
||||||
|
updateSelectedCueTrack(false);
|
||||||
|
selectedIndex++;
|
||||||
|
updateSelectedCueTrack(true);
|
||||||
|
tableWidget->scrollToItem(tableWidget->item(selectedIndex, 0));
|
||||||
|
}
|
||||||
|
emit changeSelectedIndex(selectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::displayCueTrackInTable(CueTrack *cueTrack, int index) {
|
||||||
|
if (tableWidget->columnCount() == 0) {
|
||||||
|
tableWidget->setColumnCount(7);
|
||||||
|
QStringList headers = {"Active", "Cue","Chan", "Name", "Vol", "State", "File"};
|
||||||
|
tableWidget->setHorizontalHeaderLabels(headers);
|
||||||
|
}
|
||||||
|
if (index == -1)
|
||||||
|
index = tableWidget->rowCount();
|
||||||
|
tableWidget->insertRow(index);
|
||||||
|
|
||||||
|
tableWidget->setItem(index, 0, new QTableWidgetItem(cueTrack->active ? "Yes" : "No"));
|
||||||
|
tableWidget->setItem(index, 1, new QTableWidgetItem(QStringLiteral("%1").arg(cueTrack->userNumber, 3, 10, QLatin1Char('0'))));
|
||||||
|
tableWidget->setItem(index, 2, new QTableWidgetItem(QString::number(cueTrack->audioLayer)));
|
||||||
|
tableWidget->setItem(index, 3, new QTableWidgetItem(cueTrack->name.data()));
|
||||||
|
tableWidget->setItem(index, 4, new QTableWidgetItem(QString::number(cueTrack->volume)));
|
||||||
|
QString statusStr;
|
||||||
|
statusStr = statusToString(cueTrack->status);
|
||||||
|
tableWidget->setItem(index, 5, new QTableWidgetItem(statusStr));
|
||||||
|
tableWidget->setItem(index, 6, new QTableWidgetItem(*getFileName(cueTrack->filePath)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::updateSelectedCueTrack(bool highlightRow) {
|
||||||
|
if (selectedIndex >= 0 && selectedIndex < tableWidget->rowCount()) {
|
||||||
|
QBrush backgroundBrush(highlightRow ? QColor(248, 248, 200) : Qt::white);
|
||||||
|
for (int column = 0; column < tableWidget->columnCount(); ++column) {
|
||||||
|
QTableWidgetItem *item = tableWidget->item(selectedIndex, column);
|
||||||
|
if (!item) {
|
||||||
|
item = new QTableWidgetItem();
|
||||||
|
tableWidget->setItem(selectedIndex, column, item);
|
||||||
|
}
|
||||||
|
item->setBackground(backgroundBrush);
|
||||||
|
}
|
||||||
|
tableWidget->resizeColumnsToContents();
|
||||||
|
tableWidget->resizeRowsToContents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::cueTrackLoadDefaults(CueTrack * t)
|
||||||
|
{
|
||||||
|
t->active = false;
|
||||||
|
t->audioLayer = 0;
|
||||||
|
t->bus1 = 100;
|
||||||
|
t->bus2 = 100;
|
||||||
|
t->entryPoint = 0;
|
||||||
|
t->exitPoint = 255;
|
||||||
|
t->fadeIn = 2;
|
||||||
|
t->fadeOut = 2;
|
||||||
|
t->waitIn = 0;
|
||||||
|
t->waitOut = 0;
|
||||||
|
t->pan = 0;
|
||||||
|
t->pitch = 1;
|
||||||
|
t->status = Status::PlayingOnce;
|
||||||
|
lastUserCueNumber += 10;
|
||||||
|
t->userNumber = lastUserCueNumber;
|
||||||
|
t->volume = 80;
|
||||||
|
t->stopAtEnd = true;
|
||||||
|
t->filePath = "";
|
||||||
|
t->duration = 0;
|
||||||
|
t->multi = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::createNewCueTrack()
|
||||||
|
{
|
||||||
|
CueTrack *t = new CueTrack;
|
||||||
|
cueTrackLoadDefaults(t);
|
||||||
|
EditCueTrackWidget dialog(t, this);
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
t->active = false;
|
||||||
|
addCueTrack(t);
|
||||||
|
if (m_size == 1)
|
||||||
|
{
|
||||||
|
updateSelectedCueTrack(true);
|
||||||
|
emit changeSelectedIndex(0);
|
||||||
|
} else
|
||||||
|
redrawCueTrackList();
|
||||||
|
if (lastUserCueNumber < t->userNumber)
|
||||||
|
lastUserCueNumber = t->userNumber;
|
||||||
|
} else
|
||||||
|
delete (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::editCueTrack()
|
||||||
|
{
|
||||||
|
CueTrack *current = getTrackAtIndex(selectedIndex);
|
||||||
|
EditCueTrackWidget dialog(current, this);
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
copyCueTrack(dialog.cueTrack, current);
|
||||||
|
redrawCueTrackList();
|
||||||
|
emit changeSelectedIndex(selectedIndex);
|
||||||
|
}
|
||||||
|
if (lastUserCueNumber < current->userNumber)
|
||||||
|
lastUserCueNumber = current->userNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::deleteCueTrack()
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton reply;
|
||||||
|
reply = QMessageBox::question(this, "Delete Cue Track", "Are you sure you want to delete this cue track?",
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
if (reply == QMessageBox::Yes) {
|
||||||
|
removeCueTrack(selectedIndex);
|
||||||
|
if (selectedIndex >= m_size)
|
||||||
|
{
|
||||||
|
selectedIndex = m_size - 1;
|
||||||
|
emit changeSelectedIndex(selectedIndex);
|
||||||
|
}
|
||||||
|
redrawCueTrackList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::copyCueTrack(CueTrack *src, CueTrack *dst)
|
||||||
|
{
|
||||||
|
dst->active = src->active;
|
||||||
|
dst->audioLayer = src->audioLayer;
|
||||||
|
dst->bus1 = src->bus1;
|
||||||
|
dst->bus2 = src->bus2;
|
||||||
|
dst->entryPoint = src->entryPoint;
|
||||||
|
dst->exitPoint = src->exitPoint;
|
||||||
|
dst->fadeIn = src->fadeIn;
|
||||||
|
dst->fadeOut = src->fadeOut;
|
||||||
|
dst->waitIn = src->waitIn;
|
||||||
|
dst->waitOut = src->waitOut;
|
||||||
|
dst->pan = src->pan;
|
||||||
|
dst->pitch = src->pitch;
|
||||||
|
dst->status = src->status;
|
||||||
|
dst->userNumber = src->userNumber;
|
||||||
|
dst->volume = src->volume;
|
||||||
|
dst->stopAtEnd = src->stopAtEnd;
|
||||||
|
dst->name = src->name;
|
||||||
|
dst->description = src->description;
|
||||||
|
dst->filePath = src->filePath;
|
||||||
|
dst->duration = src->duration;
|
||||||
|
dst->multi = src->multi;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString *CueTrackListWidget::getFileName(std::string s)
|
||||||
|
{
|
||||||
|
size_t bar = s.rfind("/");
|
||||||
|
std::string tmp = s.substr(bar + 1, strlen(s.data()));
|
||||||
|
QString *ret = new QString(tmp.data());
|
||||||
|
ret->truncate(64);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::sortCueTrackList()
|
||||||
|
{
|
||||||
|
std::sort(cueTracks.begin(), cueTracks.end(), [](CueTrack *a, CueTrack *b) {
|
||||||
|
return a->userNumber < b->userNumber;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::redrawCueTrackList()
|
||||||
|
{
|
||||||
|
if (!m_size)
|
||||||
|
return;
|
||||||
|
int selected = cueTracks.at(selectedIndex)->userNumber;
|
||||||
|
clearTableWidget();
|
||||||
|
tableWidget->setColumnCount(7);
|
||||||
|
QStringList headers = {"Active", "Cue","Chan", "Name", "Vol", "State", "File"};
|
||||||
|
tableWidget->setHorizontalHeaderLabels(headers);
|
||||||
|
sortCueTrackList();
|
||||||
|
selectedIndex = 0;
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
displayCueTrackInTable(cueTracks.at(i), i);
|
||||||
|
}
|
||||||
|
selectedIndex = 0;
|
||||||
|
while (cueTracks.at(selectedIndex)->userNumber != selected)
|
||||||
|
{
|
||||||
|
selectedIndex++;
|
||||||
|
}
|
||||||
|
updateSelectedCueTrack(true);
|
||||||
|
tableWidget->resizeColumnsToContents();
|
||||||
|
tableWidget->resizeRowsToContents();
|
||||||
|
tableWidget->scrollToItem(tableWidget->item(selectedIndex, 0));
|
||||||
|
tableWidget->blockSignals(false);
|
||||||
|
emit changeSelectedIndex(selectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::loadCueTrackList(std::string filename)
|
||||||
|
{
|
||||||
|
qDebug() << "loading cue list from " << filename.data();
|
||||||
|
QFile file(QString::fromStdString(filename));
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
std::cerr << "No se pudo abrir el archivo para lectura" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QXmlStreamReader xmlReader(&file);
|
||||||
|
clearCueTrackList();
|
||||||
|
lastUserCueNumber = 0;
|
||||||
|
while (!xmlReader.atEnd() && !xmlReader.hasError())
|
||||||
|
{
|
||||||
|
QXmlStreamReader::TokenType token = xmlReader.readNext();
|
||||||
|
if (token == QXmlStreamReader::StartElement)
|
||||||
|
{
|
||||||
|
if (xmlReader.name() == "CueTrack")
|
||||||
|
{
|
||||||
|
CueTrack *t = new CueTrack;
|
||||||
|
while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement && xmlReader.name() == "CueTrack"))
|
||||||
|
{
|
||||||
|
if (xmlReader.tokenType() == QXmlStreamReader::StartElement)
|
||||||
|
{
|
||||||
|
QString elementName = xmlReader.name().toString();
|
||||||
|
xmlReader.readNext();
|
||||||
|
if (xmlReader.tokenType() == QXmlStreamReader::Characters)
|
||||||
|
{
|
||||||
|
if (elementName == "filePath") {
|
||||||
|
t->filePath = xmlReader.text().toString().toStdString();
|
||||||
|
}
|
||||||
|
else if (elementName == "volume") {
|
||||||
|
t->volume = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "pan") {
|
||||||
|
t->pan = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "pitch") {
|
||||||
|
t->pitch = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "bus1") {
|
||||||
|
t->bus1 = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "bus2") {
|
||||||
|
t->bus2 = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "status") {
|
||||||
|
QString tmp = xmlReader.text().toString();
|
||||||
|
t->status = stringToStatus(&tmp);
|
||||||
|
}
|
||||||
|
else if (elementName == "fadeOut") {
|
||||||
|
t->fadeOut = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "fadeIn") {
|
||||||
|
t->fadeIn = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "waitIn") {
|
||||||
|
t->waitIn = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "waitOut") {
|
||||||
|
t->waitOut = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "stopAtEnd") {
|
||||||
|
QString tmp = xmlReader.text().toString().toLower();
|
||||||
|
if (tmp.compare("false"))
|
||||||
|
t->stopAtEnd = true;
|
||||||
|
else {
|
||||||
|
t->stopAtEnd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elementName == "name") {
|
||||||
|
t->name = xmlReader.text().toString().toStdString();
|
||||||
|
}
|
||||||
|
else if (elementName == "description") {
|
||||||
|
t->description = xmlReader.text().toString().toStdString();
|
||||||
|
}
|
||||||
|
else if (elementName == "userNumber") {
|
||||||
|
t->userNumber = xmlReader.text().toInt();
|
||||||
|
if (t->userNumber > lastUserCueNumber)
|
||||||
|
{
|
||||||
|
lastUserCueNumber = t->userNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elementName == "entryPoint") {
|
||||||
|
t->entryPoint = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "exitPoint") {
|
||||||
|
t->exitPoint = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "audioLayer") {
|
||||||
|
t->audioLayer = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "duration") {
|
||||||
|
t->duration = xmlReader.text().toInt();
|
||||||
|
}
|
||||||
|
else if (elementName == "multi") {
|
||||||
|
QString tmp = xmlReader.text().toString().toLower();
|
||||||
|
if (tmp.compare("false"))
|
||||||
|
t->multi = true;
|
||||||
|
else {
|
||||||
|
t->multi = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t->active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlReader.readNext();
|
||||||
|
}
|
||||||
|
addCueTrack(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xmlReader.hasError())
|
||||||
|
{
|
||||||
|
std::cerr << "Error al leer el archivo XML: " << xmlReader.errorString().toStdString() << std::endl;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
redrawCueTrackList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::saveCueTrackList(std::string filename)
|
||||||
|
{
|
||||||
|
qDebug() << "saving cue list to " << filename.data();
|
||||||
|
std::ofstream file(filename);
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
|
file << "<CueTrackList>\n";
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
file << cueTrackToXml(*cueTracks.at(i)) << std::endl;
|
||||||
|
}
|
||||||
|
file << "</CueTrackList>\n";
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CueTrackListWidget::cueTrackToXml(const CueTrack& cueTrack)
|
||||||
|
{
|
||||||
|
std::string xml = " <CueTrack>\n";
|
||||||
|
xml += " <filePath>" + cueTrack.filePath + "</filePath>\n";
|
||||||
|
xml += " <volume>" + std::to_string(cueTrack.volume) + "</volume>\n";
|
||||||
|
xml += " <pan>" + std::to_string(cueTrack.pan) + "</pan>\n";
|
||||||
|
xml += " <pitch>" + std::to_string(cueTrack.pitch) + "</pitch>\n";
|
||||||
|
xml += " <bus1>" + std::to_string(cueTrack.bus1) + "</bus1>\n";
|
||||||
|
xml += " <bus2>" + std::to_string(cueTrack.bus2) + "</bus2>\n";
|
||||||
|
xml += " <status>";
|
||||||
|
xml += statusToString(cueTrack.status);
|
||||||
|
xml += "</status>\n";
|
||||||
|
xml += " <fadeOut>" + std::to_string(cueTrack.fadeOut) + "</fadeOut>\n";
|
||||||
|
xml += " <fadeIn>" + std::to_string(cueTrack.fadeIn) + "</fadeIn>\n";
|
||||||
|
xml += " <waitIn>" + std::to_string(cueTrack.waitIn) + "</waitIn>\n";
|
||||||
|
xml += " <waitOut>" + std::to_string(cueTrack.waitOut) + "</waitOut>\n";
|
||||||
|
xml += " <stopAtEnd>";
|
||||||
|
xml += (cueTrack.stopAtEnd ? "true" : "false");
|
||||||
|
xml += "</stopAtEnd>\n";
|
||||||
|
xml += " <name>" + cueTrack.name + "</name>\n";
|
||||||
|
xml += " <description>" + cueTrack.description + "</description>\n";
|
||||||
|
xml += " <userNumber>" + std::to_string(cueTrack.userNumber) + "</userNumber>\n";
|
||||||
|
xml += " <entryPoint>" + std::to_string(cueTrack.entryPoint) + "</entryPoint>\n";
|
||||||
|
xml += " <exitPoint>" + std::to_string(cueTrack.exitPoint) + "</exitPoint>\n";
|
||||||
|
xml += " <audioLayer>" + std::to_string(cueTrack.audioLayer) + "</audioLayer>\n";
|
||||||
|
xml += " <duration>" + std::to_string(cueTrack.duration) + "</duration>\n";
|
||||||
|
xml += " <multi>";
|
||||||
|
xml += (cueTrack.multi ? "true" : "false");
|
||||||
|
xml += "</multi>\n";
|
||||||
|
xml += " </CueTrack>\n";
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::clearCueTrackList()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
delete cueTracks.at(i);
|
||||||
|
}
|
||||||
|
cueTracks.clear();
|
||||||
|
m_size = 0;
|
||||||
|
selectedIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
|
void saveCueTrackToXml(const CueTrack& cueTrack, const QString& filename) {
|
||||||
|
QFile file(filename);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
qInfo() << "Can not open file " << filename << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QXmlStreamWriter xmlWriter(&file);
|
||||||
|
xmlWriter.setAutoFormatting(true);
|
||||||
|
xmlWriter.writeStartDocument();
|
||||||
|
xmlWriter.writeStartElement("CueTrack");
|
||||||
|
|
||||||
|
xmlWriter.writeTextElement("filePath", QString::fromStdString(cueTrack.filePath));
|
||||||
|
xmlWriter.writeTextElement("volume", QString::number(cueTrack.volume));
|
||||||
|
xmlWriter.writeTextElement("pan", QString::number(cueTrack.pan));
|
||||||
|
xmlWriter.writeTextElement("pitch", QString::number(cueTrack.pitch));
|
||||||
|
xmlWriter.writeTextElement("bus1", QString::number(cueTrack.bus1));
|
||||||
|
xmlWriter.writeTextElement("bus2", QString::number(cueTrack.bus2));
|
||||||
|
xmlWriter.writeTextElement("status", statusToString(cueTrack.status));
|
||||||
|
xmlWriter.writeTextElement("fadeOut", QString::number(cueTrack.fadeOut));
|
||||||
|
xmlWriter.writeTextElement("fadeIn", QString::number(cueTrack.fadeIn));
|
||||||
|
xmlWriter.writeTextElement("waitIn", QString::number(cueTrack.waitIn));
|
||||||
|
xmlWriter.writeTextElement("waitOut", QString::number(cueTrack.waitOut));
|
||||||
|
xmlWriter.writeTextElement("stopAtEnd", cueTrack.stopAtEnd ? "true" : "false");
|
||||||
|
xmlWriter.writeTextElement("name", QString::fromStdString(cueTrack.name));
|
||||||
|
xmlWriter.writeTextElement("description", QString::fromStdString(cueTrack.description));
|
||||||
|
xmlWriter.writeTextElement("userNumber", QString::number(cueTrack.userNumber));
|
||||||
|
xmlWriter.writeTextElement("entryPoint", QString::number(cueTrack.entryPoint));
|
||||||
|
xmlWriter.writeTextElement("exitPoint", QString::number(cueTrack.exitPoint));
|
||||||
|
xmlWriter.writeTextElement("audioLayer", QString::number(cueTrack.audioLayer));
|
||||||
|
|
||||||
|
xmlWriter.writeEndElement();
|
||||||
|
xmlWriter.writeEndDocument();
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QString>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
CueTrack loadCueTrackFromXml(const QString& filename) {
|
||||||
|
QFile file(filename);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
throw std::runtime_error("No se pudo abrir el archivo");
|
||||||
|
}
|
||||||
|
|
||||||
|
QXmlStreamReader xmlReader(&file);
|
||||||
|
CueTrack cueTrack;
|
||||||
|
|
||||||
|
while (!xmlReader.atEnd() && !xmlReader.hasError()) {
|
||||||
|
QXmlStreamReader::TokenType token = xmlReader.readNext();
|
||||||
|
if (token == QXmlStreamReader::StartElement) {
|
||||||
|
const QString elementName = xmlReader.name().toString();
|
||||||
|
if (elementName == "filePath") {
|
||||||
|
cueTrack.filePath = xmlReader.readElementText().toStdString();
|
||||||
|
} else if (elementName == "vol") {
|
||||||
|
cueTrack.volume = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "pan") {
|
||||||
|
cueTrack.pan = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "pitch") {
|
||||||
|
cueTrack.pitch = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "bus1") {
|
||||||
|
cueTrack.bus1 = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "bus2") {
|
||||||
|
cueTrack.bus2 = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "state") {
|
||||||
|
QString tmp = xmlReader.readElementText();
|
||||||
|
cueTrack.status = stringToStatus(&tmp);
|
||||||
|
} else if (elementName == "fadeOut") {
|
||||||
|
cueTrack.fadeOut = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "fadeIn") {
|
||||||
|
cueTrack.fadeIn = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "waitIn") {
|
||||||
|
cueTrack.waitIn = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "waitOut") {
|
||||||
|
cueTrack.waitOut = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "stopAtEnd") {
|
||||||
|
cueTrack.stopAtEnd = xmlReader.readElementText() == "true";
|
||||||
|
} else if (elementName == "name") {
|
||||||
|
cueTrack.name = xmlReader.readElementText().toStdString();
|
||||||
|
} else if (elementName == "description") {
|
||||||
|
cueTrack.description = xmlReader.readElementText().toStdString();
|
||||||
|
} else if (elementName == "userNumber") {
|
||||||
|
cueTrack.userNumber = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "entryPoint") {
|
||||||
|
cueTrack.entryPoint = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "exitPoint") {
|
||||||
|
cueTrack.exitPoint = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "audioLayer") {
|
||||||
|
cueTrack.audioLayer = xmlReader.readElementText().toInt();
|
||||||
|
} else if (elementName == "duration") {
|
||||||
|
cueTrack.duration = xmlReader.readElementText().toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xmlReader.hasError()) {
|
||||||
|
throw std::runtime_error("Error al parsear el archivo XML");
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
return cueTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::clearTableWidget()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
tableWidget->removeRow(i);
|
||||||
|
}
|
||||||
|
tableWidget->clear();
|
||||||
|
tableWidget->setRowCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::cueTrackAtEnd(int layer)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
CueTrack * cur = cueTracks.at(i);
|
||||||
|
if (cur->audioLayer == layer)
|
||||||
|
{
|
||||||
|
cur->active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redrawCueTrackList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::copyCueTrack() {
|
||||||
|
if (selectedIndex >= 0 && selectedIndex < m_size) {
|
||||||
|
delete copiedCue;
|
||||||
|
copiedCue = new CueTrack(*cueTracks.at(selectedIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::cutCueTrack() {
|
||||||
|
if (selectedIndex >= 0 && selectedIndex < m_size) {
|
||||||
|
delete copiedCue;
|
||||||
|
copiedCue = new CueTrack(*cueTracks.at(selectedIndex));
|
||||||
|
removeCueTrack(selectedIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackListWidget::pasteCueTrack() {
|
||||||
|
if (copiedCue != nullptr) {
|
||||||
|
CueTrack* newCue = new CueTrack(*copiedCue);
|
||||||
|
addCueTrack(newCue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
66
src/cuetracklistwidget.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef CUETRACKLISTWIDGET_H
|
||||||
|
#define CUETRACKLISTWIDGET_H
|
||||||
|
#include <vector>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <QTableWidgetItem>
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
class CueTrackListWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CueTrackListWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
CueTrack* getSelectedTrack(bool advance);
|
||||||
|
void createNewCueTrack();
|
||||||
|
void editCueTrack();
|
||||||
|
void deleteCueTrack();
|
||||||
|
int getSelectedIndex() { return selectedIndex; };
|
||||||
|
CueTrack* getTrackAtIndex(int index);
|
||||||
|
QString *getFileName(std::string s);
|
||||||
|
void loadCueTrackList(std::string filename);
|
||||||
|
void saveCueTrackList(std::string filename);
|
||||||
|
void clearCueTrackList();
|
||||||
|
void setLastUserCueNumber(size_t n) { lastUserCueNumber = n; }
|
||||||
|
size_t getLastUserCueNumber() { return lastUserCueNumber; }
|
||||||
|
void cueTrackAtEnd(int layer);
|
||||||
|
void redrawCueTrackList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CueTrack *> cueTracks;
|
||||||
|
QVBoxLayout* layout;
|
||||||
|
QTableWidget* tableWidget;
|
||||||
|
int m_size = 0;
|
||||||
|
int size() { return m_size; }
|
||||||
|
int selectedIndex = 0;
|
||||||
|
int lastUserCueNumber = 0;
|
||||||
|
CueTrack* copiedCue = nullptr;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void addCueTrack(CueTrack* cue);
|
||||||
|
void removeCueTrack(int index);
|
||||||
|
void key_up();
|
||||||
|
void key_down();
|
||||||
|
void displayCueTrackInTable(CueTrack *cueTrack, int index);
|
||||||
|
void updateSelectedCueTrack(bool highlightRow);
|
||||||
|
void cueTrackLoadDefaults(CueTrack * t);
|
||||||
|
void copyCueTrack(CueTrack *src, CueTrack *dst);
|
||||||
|
void sortCueTrackList();
|
||||||
|
void clearTableWidget();
|
||||||
|
std::string cueTrackToXml(const CueTrack& cueTrack);
|
||||||
|
void copyCueTrack();
|
||||||
|
void pasteCueTrack();
|
||||||
|
void cutCueTrack();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void changeSelectedIndex(int index);
|
||||||
|
void goAction(int channel);
|
||||||
|
};
|
||||||
|
#endif
|
148
src/cuetrackwidget.cpp
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
#include "cuetrackwidget.h"
|
||||||
|
#include "ui_cuetrackwidget.h"
|
||||||
|
|
||||||
|
CueTrackWidget::CueTrackWidget(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::CueTrackWidget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
tlFade.setFrameRange(0, 100);
|
||||||
|
tlWaitIn.setFrameRange(0, 100);
|
||||||
|
tlWaitOut.setFrameRange(0, 100);
|
||||||
|
connect(&tlFade, &QTimeLine::frameChanged, ui->cueProgressBar, &QProgressBar::setValue);
|
||||||
|
connect(&tlWaitIn, &QTimeLine::frameChanged, ui->cueProgressBar, &QProgressBar::setValue);
|
||||||
|
connect(&tlWaitOut, &QTimeLine::frameChanged, ui->cueProgressBar, &QProgressBar::setValue);
|
||||||
|
connect(&tlFade, SIGNAL(finished()), this, SLOT(fadeSlot()));
|
||||||
|
connect(&tlWaitIn, SIGNAL(finished()), this, SLOT(waitInSlot()));
|
||||||
|
connect(&tlWaitOut, SIGNAL(finished()), this, SLOT(waitOutSlot()));
|
||||||
|
connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play()));
|
||||||
|
connect(ui->stopButton, SIGNAL(clicked()), this, SLOT(stop()));
|
||||||
|
connect(ui->pauseButton, SIGNAL(clicked()), this, SLOT(pause()));
|
||||||
|
connect(ui->fadeInButton, SIGNAL(clicked()), this, SLOT(fadeIn()));
|
||||||
|
connect(ui->fadeOutButton, SIGNAL(clicked()), this, SLOT(fadeOut()));
|
||||||
|
connect(ui->muteButton, SIGNAL(clicked()), this, SLOT(mute()));
|
||||||
|
}
|
||||||
|
|
||||||
|
CueTrackWidget::~CueTrackWidget()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::loadCueTrack(CueTrack* track)
|
||||||
|
{
|
||||||
|
ui->cueName->setText(track->name.data());
|
||||||
|
ui->cueNumber->display(track->userNumber);
|
||||||
|
ui->vol->display(track->volume);
|
||||||
|
ui->pan->display(track->pan);
|
||||||
|
ui->pitch->display(track->pitch);
|
||||||
|
ui->bus1->display(track->bus1);
|
||||||
|
ui->bus2->display(track->bus2);
|
||||||
|
ui->fade->display(track->fadeIn);
|
||||||
|
ui->waitIn->display(track->waitIn);
|
||||||
|
ui->waitOut->display(track->waitOut);
|
||||||
|
ui->halt->setChecked(track->stopAtEnd);
|
||||||
|
QFileInfo fileInfo(track->filePath.data());
|
||||||
|
fileInfo.fileName().truncate(64);
|
||||||
|
ui->mediaFileName->setText(fileInfo.fileName());
|
||||||
|
ui->status->setText(statusToString(track->status));
|
||||||
|
ui->audioLayer->display(track->audioLayer);
|
||||||
|
ui->multi->setChecked(track->multi);
|
||||||
|
ui->fadeOut->display(track->fadeOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::go()
|
||||||
|
{
|
||||||
|
tlFade.stop();
|
||||||
|
tlWaitIn.stop();
|
||||||
|
tlWaitOut.stop();
|
||||||
|
ui->cueProgressBar->setValue(0);
|
||||||
|
if (ui->waitIn->value() > 0)
|
||||||
|
{
|
||||||
|
tlWaitIn.setDuration(ui->waitIn->value() * 1000);
|
||||||
|
tlWaitIn.start();
|
||||||
|
ui->cueProgressBar->setStyleSheet("QProgressBar::chunk { background-color: #FF0000; }");
|
||||||
|
} else {
|
||||||
|
waitInSlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::waitInSlot()
|
||||||
|
{
|
||||||
|
emit goAction(ui->audioLayer->intValue());
|
||||||
|
if (ui->fade->value() > 0) {
|
||||||
|
tlFade.setDuration(ui->fade->value() * 1000);
|
||||||
|
tlFade.start();
|
||||||
|
ui->cueProgressBar->setStyleSheet("QProgressBar::chunk { background-color: #00FF00; }");
|
||||||
|
} else {
|
||||||
|
fadeSlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::fadeSlot()
|
||||||
|
{
|
||||||
|
if (ui->waitOut->value() > 0) {
|
||||||
|
tlWaitOut.setDuration(ui->waitOut->value() * 1000);
|
||||||
|
tlWaitOut.start();
|
||||||
|
ui->cueProgressBar->setStyleSheet("QProgressBar::chunk { background-color: #FF0000; }");
|
||||||
|
} else {
|
||||||
|
waitOutSlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::waitOutSlot()
|
||||||
|
{
|
||||||
|
ui->cueProgressBar->setStyleSheet("QProgressBar::chunk { background-color: #0000FF; }");
|
||||||
|
emit cueFinished(ui->audioLayer->intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::setNextCue()
|
||||||
|
{
|
||||||
|
ui->cueProgressBar->setDisabled(true);
|
||||||
|
ui->cueProgressBar->hide();
|
||||||
|
ui->audioControlLayout->setEnabled(false);
|
||||||
|
QList<int> list = { 1, 0 };
|
||||||
|
ui->cueValues->setSizes(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::play()
|
||||||
|
{
|
||||||
|
QString t = ui->status->text();
|
||||||
|
emit changeStatus(ui->audioLayer->intValue(), stringToStatus(&t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::stop()
|
||||||
|
{
|
||||||
|
emit changeStatus(ui->audioLayer->intValue(), Status::Stopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::pause()
|
||||||
|
{
|
||||||
|
emit changeStatus(ui->audioLayer->intValue(), Status::Paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::fadeIn()
|
||||||
|
{
|
||||||
|
emit changeVol(ui->audioLayer->intValue(), Slider::Volume, ui->vol->value() * 655.35, ui->fade->value() * 1000, ui->fadeOut->value() * 1000);
|
||||||
|
muted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::fadeOut()
|
||||||
|
{
|
||||||
|
emit changeVol(ui->audioLayer->intValue(), Slider::Volume, 0, ui->fade->value() * 1000, ui->fadeOut->value() * 1000);
|
||||||
|
muted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CueTrackWidget::mute()
|
||||||
|
{
|
||||||
|
if (muted)
|
||||||
|
{
|
||||||
|
emit changeVol(ui->audioLayer->intValue(), Slider::Volume, ui->vol->value() * 655.35, 0, 0);
|
||||||
|
muted = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit changeVol(ui->audioLayer->intValue(), Slider::Volume, 0, 0, 0);
|
||||||
|
muted = true;
|
||||||
|
}
|
||||||
|
}
|
52
src/cuetrackwidget.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef CUETRACKWIDGET_H
|
||||||
|
#define CUETRACKWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QTimeLine>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "dialgroup.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CueTrackWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CueTrackWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CueTrackWidget(QWidget *parent = nullptr);
|
||||||
|
~CueTrackWidget();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void loadCueTrack(CueTrack* track);
|
||||||
|
void go();
|
||||||
|
void setNextCue();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::CueTrackWidget *ui;
|
||||||
|
QTimeLine tlFade;
|
||||||
|
QTimeLine tlWaitIn;
|
||||||
|
QTimeLine tlWaitOut;
|
||||||
|
bool muted = false;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void fadeSlot();
|
||||||
|
void waitInSlot();
|
||||||
|
void waitOutSlot();
|
||||||
|
void play();
|
||||||
|
void stop();
|
||||||
|
void pause();
|
||||||
|
void fadeIn();
|
||||||
|
void fadeOut();
|
||||||
|
void mute();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void cueFinished(int layer);
|
||||||
|
void goAction(int layer);
|
||||||
|
void changeStatus(int layer, Status status);
|
||||||
|
void changeVol(int layer, Slider s, int value, int fadein, int fadeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CUETRACKWIDGET_H
|
1142
src/cuetrackwidget.ui
Normal file
|
@ -4,7 +4,7 @@
|
||||||
#define VERSION "LibreMediaServerAudio v0.2.0 Antigona"
|
#define VERSION "LibreMediaServerAudio v0.2.0 Antigona"
|
||||||
#define COPYRIGHT "(C) 2014-2024 Santi Noreña <lms@criptomart.net>"
|
#define COPYRIGHT "(C) 2014-2024 Santi Noreña <lms@criptomart.net>"
|
||||||
#define LICENSE "GPL3 Licensed. See LICENSE.txt."
|
#define LICENSE "GPL3 Licensed. See LICENSE.txt."
|
||||||
#define DEFAULT_FILE "lms-audio.xlm"
|
#define DEFAULT_FILE "lms-audio.xml"
|
||||||
#define MAX_LAYERS 4
|
#define MAX_LAYERS 4
|
||||||
#define MAX_AUDIODEVICES 8
|
#define MAX_AUDIODEVICES 8
|
||||||
#define FORMAT ma_format_f32 /* Must always be f32. */
|
#define FORMAT ma_format_f32 /* Must always be f32. */
|
||||||
|
@ -57,12 +57,25 @@ constexpr const char* statusToString(Status e) noexcept
|
||||||
case Status::Iddle: return "Iddle";
|
case Status::Iddle: return "Iddle";
|
||||||
case Status::PlayingFolder: return "Play Folder";
|
case Status::PlayingFolder: return "Play Folder";
|
||||||
case Status::PlayingFolderLoop: return "Play Folder Loop";
|
case Status::PlayingFolderLoop: return "Play Folder Loop";
|
||||||
case Status::PlayingFolderRandom: return "Playing Folder Random";
|
case Status::PlayingFolderRandom: return "Play Folder Random";
|
||||||
default: return "--++--";
|
default: return "--++--";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
static Status stringToStatus(QString *statusStr) {
|
||||||
|
if (!statusStr->compare("Stop")) return Stopped;
|
||||||
|
else if (!statusStr->compare("Paused") ) return Paused;
|
||||||
|
else if (!statusStr->compare("Play 1")) return PlayingOnce;
|
||||||
|
else if (!statusStr->compare("Play Loop")) return PlayingLoop;
|
||||||
|
else if (!statusStr->compare("Iddle")) return Iddle;
|
||||||
|
else if (!statusStr->compare("Play Folder")) return PlayingFolder;
|
||||||
|
else if (!statusStr->compare("Play Folder Loop")) return PlayingFolderLoop;
|
||||||
|
else if (!statusStr->compare("Play Folder Random")) return PlayingFolderRandom;
|
||||||
|
else return Iddle;
|
||||||
|
}
|
||||||
|
|
||||||
struct layerData {
|
struct layerData {
|
||||||
QString media;
|
QString media;
|
||||||
Status status;
|
Status status;
|
||||||
|
@ -78,6 +91,33 @@ struct layerData {
|
||||||
int bus1Vol;
|
int bus1Vol;
|
||||||
int bus2Vol;
|
int bus2Vol;
|
||||||
float level;
|
float level;
|
||||||
|
int fadeIn;
|
||||||
|
int fadeOut;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CueTrack {
|
||||||
|
std::string filePath;
|
||||||
|
int volume = 0; // 0 - 65535 ToDo: change to db -85 - 0
|
||||||
|
int pan = 128; // 0 - 255
|
||||||
|
int pitch = 128; // 0 - 255
|
||||||
|
int bus1 = 255; // 0 - 255
|
||||||
|
int bus2 = 255; // 0 - 255
|
||||||
|
Status status;
|
||||||
|
int fadeOut = 3; // ToDo: change to float or milliseconds
|
||||||
|
int fadeIn = 3;
|
||||||
|
int waitIn = 0;
|
||||||
|
int waitOut = 0;
|
||||||
|
bool stopAtEnd = false; // trigger next cue when this is executed
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
int userNumber; // cue user id
|
||||||
|
int entryPoint; // 0 - 255
|
||||||
|
int exitPoint; // 0 - 255
|
||||||
|
int audioLayer; // internal audio layer used when cue is loaded
|
||||||
|
bool active; // the cue is playing
|
||||||
|
int duration; // media duration in milliseconds
|
||||||
|
bool multi; // launch next cue at same time, not waiting for this to finish.
|
||||||
|
};
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
#endif // DEFINES_H
|
#endif // DEFINES_H
|
||||||
|
|
67
src/dialgroup.cpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#include <cmath>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include "dialgroup.h"
|
||||||
|
|
||||||
|
DialGroup::DialGroup(QString name,
|
||||||
|
int min,
|
||||||
|
int max,
|
||||||
|
int decimals,
|
||||||
|
QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
|
layout->setAlignment(Qt::AlignHCenter);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
slider.setFocusPolicy(Qt::NoFocus);
|
||||||
|
slider.setRange(min, max);
|
||||||
|
slider.setValue(min + max / 2);
|
||||||
|
slider.setToolTip(name);
|
||||||
|
slider.setContentsMargins(0, 0, 0, 0);
|
||||||
|
/*
|
||||||
|
slider.setMinimumHeight(0);
|
||||||
|
slider.setSingleStep(1);
|
||||||
|
slider.setMinimumWidth(50);
|
||||||
|
slider.setStyleSheet("QDial {"
|
||||||
|
"border: 1px solid #aa8895;"
|
||||||
|
"background: #20182d;"
|
||||||
|
"margin: 0px;}"
|
||||||
|
"QSlider::groove:vertical {"
|
||||||
|
"border: 1px solid #999999;"
|
||||||
|
"width: 25px;}"
|
||||||
|
"QDial::tickmarks:vertical {"
|
||||||
|
"background-color: black;"
|
||||||
|
"background: red;"
|
||||||
|
"color: white;}"
|
||||||
|
*/
|
||||||
|
valueBox.setFocusPolicy(Qt::NoFocus);
|
||||||
|
valueBox.setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
|
valueBox.setMinimumWidth(50);
|
||||||
|
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);
|
||||||
|
layout->addWidget(&slider);
|
||||||
|
layout->addWidget(&valueBox);
|
||||||
|
/* this->setStyleSheet("border: 1px solid #998090;"
|
||||||
|
"background-color: black;"
|
||||||
|
"margin: 1px;"
|
||||||
|
);*/
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
this->setLayout(layout);
|
||||||
|
slider.setObjectName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialGroup::setValue(float value)
|
||||||
|
{
|
||||||
|
slider.blockSignals(true);
|
||||||
|
valueBox.blockSignals(true);
|
||||||
|
slider.setValue(value);
|
||||||
|
valueBox.setValue(value);
|
||||||
|
slider.blockSignals(false);
|
||||||
|
valueBox.blockSignals(false);
|
||||||
|
}
|
30
src/dialgroup.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef DIALGROUP_H
|
||||||
|
#define DIALGROUP_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDial>
|
||||||
|
|
||||||
|
#include "clickabledoublespinbox.h"
|
||||||
|
|
||||||
|
class DialGroup : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DialGroup(QString name,
|
||||||
|
int min,
|
||||||
|
int max,
|
||||||
|
int decimals,
|
||||||
|
QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setValue(float value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDial slider;
|
||||||
|
ClickableDoubleSpinBox valueBox;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
145
src/editcuetrackwidget.cpp
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
#include "editcuetrackwidget.h"
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
EditCueTrackWidget::EditCueTrackWidget(CueTrack *cueTrack, QWidget *parent)
|
||||||
|
: QDialog(parent) {
|
||||||
|
setupUi();
|
||||||
|
connectSignals();
|
||||||
|
this->cueTrack = cueTrack;
|
||||||
|
loadCueTrack(*cueTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditCueTrackWidget::setupUi() {
|
||||||
|
QFormLayout *layout = new QFormLayout(this);
|
||||||
|
|
||||||
|
userNumberSpin = new QSpinBox(this);
|
||||||
|
userNumberSpin->setRange(0, 9999);
|
||||||
|
layout->addRow("User Number", userNumberSpin);
|
||||||
|
nameEdit = new QLineEdit(this);
|
||||||
|
layout->addRow("Name", nameEdit);
|
||||||
|
audioLayerSpin = new QSpinBox(this);
|
||||||
|
audioLayerSpin->setRange(0, MAX_LAYERS - 1);
|
||||||
|
layout->addRow("Audio Layer", audioLayerSpin);
|
||||||
|
filePathEdit = new QLineEdit(this);
|
||||||
|
layout->addRow("File Path", filePathEdit);
|
||||||
|
browseButton = new QPushButton("Browse...", this);
|
||||||
|
layout->addRow(browseButton);
|
||||||
|
statusCombo = new QComboBox(this);
|
||||||
|
layout->addRow("Status", statusCombo);
|
||||||
|
volumeSpin = new QDoubleSpinBox(this);
|
||||||
|
volumeSpin->setRange(0, 100.00f);
|
||||||
|
layout->addRow("Volume", volumeSpin);
|
||||||
|
panSpin = new QDoubleSpinBox(this);
|
||||||
|
panSpin->setRange(-1, 1);
|
||||||
|
layout->addRow("Pan", panSpin);
|
||||||
|
pitchSpin = new QDoubleSpinBox(this);
|
||||||
|
pitchSpin->setRange(0, 2);
|
||||||
|
layout->addRow("Pitch", pitchSpin);
|
||||||
|
bus1Spin = new QDoubleSpinBox(this);
|
||||||
|
bus1Spin->setRange(0, 100.00f);
|
||||||
|
layout->addRow("Bus 1", bus1Spin);
|
||||||
|
bus2Spin = new QDoubleSpinBox(this);
|
||||||
|
bus2Spin->setRange(0, 100.00f);
|
||||||
|
layout->addRow("Bus 2", bus2Spin);
|
||||||
|
fadeInSpin = new QSpinBox(this);
|
||||||
|
layout->addRow("Fade In", fadeInSpin);
|
||||||
|
fadeOutSpin = new QSpinBox(this);
|
||||||
|
fadeOutSpin->setRange(0, 60 * 60 * 24);
|
||||||
|
layout->addRow("Fade Out", fadeOutSpin);
|
||||||
|
waitInSpin = new QSpinBox(this);
|
||||||
|
layout->addRow("Wait In", waitInSpin);
|
||||||
|
waitOutSpin = new QSpinBox(this);
|
||||||
|
layout->addRow("Wait Out", waitOutSpin);
|
||||||
|
stopAtEndCheck = new QCheckBox(this);
|
||||||
|
layout->addRow("Stop At End", stopAtEndCheck);
|
||||||
|
descriptionEdit = new QLineEdit(this);
|
||||||
|
layout->addRow("Description", descriptionEdit);
|
||||||
|
entryPointSpin = new QSpinBox(this);
|
||||||
|
layout->addRow("Entry Point", entryPointSpin);
|
||||||
|
exitPointSpin = new QSpinBox(this);
|
||||||
|
layout->addRow("Exit Point", exitPointSpin);
|
||||||
|
multiCheck = new QCheckBox(this);
|
||||||
|
layout->addRow("Multi Cue", multiCheck);
|
||||||
|
statusCombo->addItem(statusToString(Status::Stopped));
|
||||||
|
statusCombo->addItem(statusToString(Status::Paused));
|
||||||
|
statusCombo->addItem(statusToString(Status::PlayingOnce));
|
||||||
|
statusCombo->addItem(statusToString(Status::PlayingLoop));
|
||||||
|
statusCombo->addItem(statusToString(Status::Iddle));
|
||||||
|
statusCombo->addItem(statusToString(Status::PlayingFolder));
|
||||||
|
statusCombo->addItem(statusToString(Status::PlayingFolderLoop));
|
||||||
|
statusCombo->addItem(statusToString(Status::PlayingFolderRandom));
|
||||||
|
saveButton = new QPushButton("Save", this);
|
||||||
|
cancelButton = new QPushButton("Cancel", this);
|
||||||
|
layout->addRow(saveButton);
|
||||||
|
layout->addRow(cancelButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditCueTrackWidget::loadCueTrack(CueTrack cueTrack) {
|
||||||
|
filePathEdit->setText(cueTrack.filePath.data());
|
||||||
|
volumeSpin->setValue(cueTrack.volume);
|
||||||
|
panSpin->setValue(cueTrack.pan);
|
||||||
|
pitchSpin->setValue(cueTrack.pitch);
|
||||||
|
bus1Spin->setValue(cueTrack.bus1);
|
||||||
|
bus2Spin->setValue(cueTrack.bus2);
|
||||||
|
fadeInSpin->setValue(cueTrack.fadeIn);
|
||||||
|
fadeOutSpin->setValue(cueTrack.fadeOut);
|
||||||
|
waitInSpin->setValue(cueTrack.waitIn);
|
||||||
|
waitOutSpin->setValue(cueTrack.waitOut);
|
||||||
|
stopAtEndCheck->setChecked(cueTrack.stopAtEnd);
|
||||||
|
nameEdit->setText(cueTrack.name.data());
|
||||||
|
descriptionEdit->setText(cueTrack.description.data());
|
||||||
|
userNumberSpin->setValue(cueTrack.userNumber);
|
||||||
|
entryPointSpin->setValue(cueTrack.entryPoint);
|
||||||
|
exitPointSpin->setValue(cueTrack.exitPoint);
|
||||||
|
audioLayerSpin->setValue(cueTrack.audioLayer);
|
||||||
|
QString tmp = statusToString(cueTrack.status);
|
||||||
|
statusCombo->setCurrentIndex(statusCombo->findText(tmp));
|
||||||
|
multiCheck->setChecked(cueTrack.multi);
|
||||||
|
}
|
||||||
|
|
||||||
|
CueTrack EditCueTrackWidget::saveCueTrack() {
|
||||||
|
CueTrack cueTrack;
|
||||||
|
cueTrack.userNumber = userNumberSpin->value();
|
||||||
|
cueTrack.name.append(nameEdit->text().toUtf8().constData());
|
||||||
|
cueTrack.audioLayer = audioLayerSpin->value();
|
||||||
|
cueTrack.filePath.append(filePathEdit->text().toUtf8().constData());
|
||||||
|
cueTrack.status = static_cast<Status>(statusCombo->currentIndex());
|
||||||
|
cueTrack.fadeIn = fadeInSpin->value();
|
||||||
|
cueTrack.fadeOut = fadeOutSpin->value();
|
||||||
|
cueTrack.waitIn = waitInSpin->value();
|
||||||
|
cueTrack.waitOut = waitOutSpin->value();
|
||||||
|
cueTrack.stopAtEnd = stopAtEndCheck->isChecked();
|
||||||
|
cueTrack.entryPoint = entryPointSpin->value();
|
||||||
|
cueTrack.exitPoint = exitPointSpin->value();
|
||||||
|
cueTrack.volume = volumeSpin->value();
|
||||||
|
cueTrack.bus1 = bus1Spin->value();
|
||||||
|
cueTrack.bus2 = bus2Spin->value();
|
||||||
|
cueTrack.pan = panSpin->value();
|
||||||
|
cueTrack.pitch = pitchSpin->value();
|
||||||
|
cueTrack.description.append(descriptionEdit->text().toUtf8().constData());
|
||||||
|
cueTrack.multi = multiCheck->isChecked();
|
||||||
|
return cueTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditCueTrackWidget::accept() {
|
||||||
|
*cueTrack = saveCueTrack();
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditCueTrackWidget::connectSignals() {
|
||||||
|
connect(saveButton, &QPushButton::clicked, this, &EditCueTrackWidget::accept);
|
||||||
|
connect(cancelButton, &QPushButton::clicked, this, &EditCueTrackWidget::reject);
|
||||||
|
connect(browseButton, &QPushButton::clicked, this, &EditCueTrackWidget::onBrowseButtonClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditCueTrackWidget::onBrowseButtonClicked() {
|
||||||
|
QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), Settings::getInstance()->getPathMedia(), tr("Audio Files (*.mp3 *.wav *.flac)"));
|
||||||
|
if (!filePath.isEmpty()) {
|
||||||
|
filePathEdit->setText(filePath);
|
||||||
|
QDir dir;
|
||||||
|
Settings::getInstance()->setPathMedia(dir.absoluteFilePath(filePath));
|
||||||
|
}
|
||||||
|
}
|
55
src/editcuetrackwidget.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef EDITCUETRACKWIDGET_H
|
||||||
|
#define EDITCUETRACKWIDGET_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
class EditCueTrackWidget : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit EditCueTrackWidget(CueTrack *cueTrack, QWidget *parent = nullptr);
|
||||||
|
CueTrack *cueTrack;
|
||||||
|
void loadCueTrack(CueTrack cueTrack);
|
||||||
|
CueTrack saveCueTrack();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUi();
|
||||||
|
void connectSignals();
|
||||||
|
void onBrowseButtonClicked();
|
||||||
|
void accept() override;
|
||||||
|
|
||||||
|
QLineEdit *filePathEdit;
|
||||||
|
QDoubleSpinBox *volumeSpin;
|
||||||
|
QDoubleSpinBox *panSpin;
|
||||||
|
QDoubleSpinBox *pitchSpin;
|
||||||
|
QDoubleSpinBox *bus1Spin;
|
||||||
|
QDoubleSpinBox *bus2Spin;
|
||||||
|
QSpinBox *fadeInSpin;
|
||||||
|
QSpinBox *fadeOutSpin;
|
||||||
|
QSpinBox *waitInSpin;
|
||||||
|
QSpinBox *waitOutSpin;
|
||||||
|
QCheckBox *stopAtEndCheck;
|
||||||
|
QLineEdit *nameEdit;
|
||||||
|
QLineEdit *descriptionEdit;
|
||||||
|
QSpinBox *userNumberSpin;
|
||||||
|
QSpinBox *entryPointSpin;
|
||||||
|
QSpinBox *exitPointSpin;
|
||||||
|
QComboBox *statusCombo;
|
||||||
|
QSpinBox *audioLayerSpin;
|
||||||
|
QCheckBox *multiCheck;
|
||||||
|
QPushButton *browseButton;
|
||||||
|
QPushButton *saveButton;
|
||||||
|
QPushButton *cancelButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EDITCUETRACKWIDGET_H
|
|
@ -36,6 +36,14 @@ FilterBankWidget::FilterBankWidget(QWidget *parent)
|
||||||
"font-size: 8px;}");
|
"font-size: 8px;}");
|
||||||
connect(m_bypass, SIGNAL(stateChanged(int)), this, SLOT(bypassChanged(int)));
|
connect(m_bypass, SIGNAL(stateChanged(int)), this, SLOT(bypassChanged(int)));
|
||||||
master->addWidget(fb[0]);
|
master->addWidget(fb[0]);
|
||||||
|
fb[0]->setFocusPolicy(Qt::NoFocus);
|
||||||
|
fb[0]->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
|
fb[0]->setValue(-1);
|
||||||
|
fb[0]->setDecimals(1);
|
||||||
|
fb[0]->setAlignment(Qt::AlignHCenter);
|
||||||
|
fb[0]->setContentsMargins(0, 0, 0, 0);
|
||||||
|
fb[0]->setMaximumWidth(66);
|
||||||
|
fb[0]->setMinimumWidth(25);
|
||||||
layout->addLayout(master);
|
layout->addLayout(master);
|
||||||
for (int i = 1; i < 13;) {
|
for (int i = 1; i < 13;) {
|
||||||
QVBoxLayout *filterLayout= new QVBoxLayout;
|
QVBoxLayout *filterLayout= new QVBoxLayout;
|
||||||
|
@ -47,6 +55,14 @@ FilterBankWidget::FilterBankWidget(QWidget *parent)
|
||||||
} else {
|
} else {
|
||||||
fb[j]->setRange(-50, 50);
|
fb[j]->setRange(-50, 50);
|
||||||
}
|
}
|
||||||
|
fb[j]->setFocusPolicy(Qt::NoFocus);
|
||||||
|
fb[j]->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
|
fb[j]->setValue(-1);
|
||||||
|
fb[j]->setDecimals(1);
|
||||||
|
fb[j]->setAlignment(Qt::AlignHCenter);
|
||||||
|
fb[j]->setContentsMargins(0, 0, 0, 0);
|
||||||
|
fb[j]->setMaximumWidth(66);
|
||||||
|
fb[j]->setMinimumWidth(25);
|
||||||
filterLayout->insertWidget(j, fb[j]);
|
filterLayout->insertWidget(j, fb[j]);
|
||||||
}
|
}
|
||||||
filterLayout->setSpacing(0);
|
filterLayout->setSpacing(0);
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
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(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(0, 0, 0, 0);
|
|
||||||
this->setStyleSheet(
|
|
||||||
"margin: 0px;"
|
|
||||||
"color: white;"
|
|
||||||
"background-color: #3f3038;"
|
|
||||||
"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();
|
|
||||||
}
|
|
106
src/libremediaserver-audio-ui.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
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-ui.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()));
|
||||||
|
connect(ui.actionLaunchShowPlayer, SIGNAL(triggered()), this, SLOT(launchShowPlayerWindow()));
|
||||||
|
connect(ui.actionAudioSetup, SIGNAL(triggered()), this, SLOT(audioSetupWindow));
|
||||||
|
this->setContentsMargins(0, 0, 0, 0);
|
||||||
|
this->setStyleSheet(
|
||||||
|
"margin: 0px;"
|
||||||
|
"color: white;"
|
||||||
|
"background-color: #3f3038;"
|
||||||
|
"selection-color: blue;"
|
||||||
|
"selection-background-color: green"
|
||||||
|
);
|
||||||
|
m_showPlayer = new ShowPlayer();
|
||||||
|
m_showPlayer->setFocus();
|
||||||
|
QShortcut *shortcut_space = new QShortcut(QKeySequence(" "), this);
|
||||||
|
QObject::connect(shortcut_space, SIGNAL(activated()), m_showPlayer, SLOT(go()));
|
||||||
|
QShortcut *shortcut_up = new QShortcut(QKeySequence("Up"), this);
|
||||||
|
QObject::connect(shortcut_up, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(key_up()));
|
||||||
|
QShortcut *shortcut_down = new QShortcut(QKeySequence("Down"), this);
|
||||||
|
QObject::connect(shortcut_down, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(key_down()));
|
||||||
|
QShortcut *shortcut_copy = new QShortcut(QKeySequence("Ctrl+C"), this);
|
||||||
|
QObject::connect(shortcut_copy, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(copyCueTrack()));
|
||||||
|
QShortcut *shortcut_cut = new QShortcut(QKeySequence("Ctrl+X"), this);
|
||||||
|
QObject::connect(shortcut_cut, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(cutCueTrack()));
|
||||||
|
QShortcut *shortcut_paste = new QShortcut(QKeySequence("Ctrl+V"), this);
|
||||||
|
QObject::connect(shortcut_paste, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(pasteCueTrack()));
|
||||||
|
QShortcut *shortcut_delete = new QShortcut(QKeySequence("Delete"), this);
|
||||||
|
QObject::connect(shortcut_delete, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(deleteCueTrack()));
|
||||||
|
QShortcut *shortcut_insert = new QShortcut(QKeySequence("Insert"), this);
|
||||||
|
QObject::connect(shortcut_insert, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(createNewCueTrack()));
|
||||||
|
QShortcut *shortcut_edit = new QShortcut(QKeySequence("e"), this);
|
||||||
|
QObject::connect(shortcut_edit, SIGNAL(activated()), m_showPlayer->ui->cueListWidget, SLOT(editCueTrack()));
|
||||||
|
Settings::getInstance()->beginGroup("mainwindow");
|
||||||
|
auto geometry = Settings::getInstance()->value("geometry", QByteArray()).toByteArray();
|
||||||
|
if (!geometry.isEmpty())
|
||||||
|
restoreGeometry(geometry);
|
||||||
|
geometry = Settings::getInstance()->value("showPlayerGeometry", QByteArray()).toByteArray();
|
||||||
|
if (!geometry.isEmpty())
|
||||||
|
m_showPlayer->restoreGeometry(geometry);
|
||||||
|
Settings::getInstance()->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
libreMediaServerAudioUi::~libreMediaServerAudioUi()
|
||||||
|
{
|
||||||
|
Settings::getInstance()->beginGroup("mainwindow");
|
||||||
|
Settings::getInstance()->setValue("size", size());
|
||||||
|
Settings::getInstance()->setValue("fullScreen", isFullScreen());
|
||||||
|
Settings::getInstance()->setValue("geometry", saveGeometry());
|
||||||
|
Settings::getInstance()->setValue("showPlayer", m_showPlayer->isVisible());
|
||||||
|
Settings::getInstance()->setValue("showPlayerSize", m_showPlayer->size());
|
||||||
|
Settings::getInstance()->setValue("showPlayerGeometry", m_showPlayer->saveGeometry());
|
||||||
|
Settings::getInstance()->endGroup();
|
||||||
|
delete m_showPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudioUi::olasetup()
|
||||||
|
{
|
||||||
|
QWebView *view = new QWebView();
|
||||||
|
view->load(QUrl("http://localhost:9090/ola.html"));
|
||||||
|
view->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudioUi::launchShowPlayerWindow()
|
||||||
|
{
|
||||||
|
m_showPlayer->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudioUi::audioSetupWindow()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -26,7 +26,8 @@
|
||||||
#include "audiowidget.h"
|
#include "audiowidget.h"
|
||||||
#include "dmxwidget.h"
|
#include "dmxwidget.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "ui_libremediaserver-audio-gui.h"
|
#include "showplayer.h"
|
||||||
|
#include "ui_libremediaserver-audio-ui.h"
|
||||||
|
|
||||||
class libreMediaServerAudioUi : public QMainWindow
|
class libreMediaServerAudioUi : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -37,12 +38,15 @@ public:
|
||||||
virtual ~libreMediaServerAudioUi();
|
virtual ~libreMediaServerAudioUi();
|
||||||
AudioWidget *m_aw;
|
AudioWidget *m_aw;
|
||||||
dmxWidget *m_dmxWidget;
|
dmxWidget *m_dmxWidget;
|
||||||
|
ShowPlayer *m_showPlayer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::LibreMediaServerAudio ui;
|
Ui::LibreMediaServerAudioUi ui;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void olasetup();
|
void olasetup();
|
||||||
|
void launchShowPlayerWindow();
|
||||||
|
void audioSetupWindow();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIBREMEDIASERVERAUDIOUI_H
|
#endif // LIBREMEDIASERVERAUDIOUI_H
|
|
@ -1,21 +1,20 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<author>Santi Noreña lms@criptomart.net</author>
|
<author>Santi Noreña lms@criptomart.net</author>
|
||||||
<class>LibreMediaServerAudio</class>
|
<class>LibreMediaServerAudioUi</class>
|
||||||
<widget class="QMainWindow" name="LibreMediaServerAudio">
|
<widget class="QMainWindow" name="LibreMediaServerAudioUi">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>640</width>
|
||||||
<height>400</height>
|
<height>800</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Unifont</family>
|
<family>Unifont</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
|
@ -23,8 +22,8 @@
|
||||||
<string>LibreMediaServer</string>
|
<string>LibreMediaServer</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset>
|
<iconset resource="../lms-resources.qrc">
|
||||||
<normaloff>../../../../criptomart/artwork/logo_v2_criptomart.net.png</normaloff>../../../../criptomart/artwork/logo_v2_criptomart.net.png</iconset>
|
<normaloff>:/buttons/resources/icon.png</normaloff>:/buttons/resources/icon.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget"/>
|
<widget class="QWidget" name="centralwidget"/>
|
||||||
<widget class="QMenuBar" name="menuBar">
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
@ -32,15 +31,17 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>640</width>
|
||||||
<height>21</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>File</string>
|
<string>Setup</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionLaunch_OLA_Setup"/>
|
<addaction name="actionLaunch_OLA_Setup"/>
|
||||||
|
<addaction name="actionLaunchShowPlayer"/>
|
||||||
|
<addaction name="actionAudioSetup"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -49,7 +50,19 @@
|
||||||
<string>OLA Setup</string>
|
<string>OLA Setup</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionLaunchShowPlayer">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Player</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAudioSetup">
|
||||||
|
<property name="text">
|
||||||
|
<string>Audio</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="../lms-resources.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
|
@ -23,13 +23,10 @@
|
||||||
|
|
||||||
libreMediaServerAudio::libreMediaServerAudio()
|
libreMediaServerAudio::libreMediaServerAudio()
|
||||||
{
|
{
|
||||||
m_settings = Settings::getInstance();
|
m_settings = Settings::getInstance(this);
|
||||||
m_settings->readFile();
|
//m_settings->readFile();
|
||||||
m_ui = m_settings->getShowUi();
|
m_ui = m_settings->getShowUi();
|
||||||
m_layersQty = m_settings->getLayersNumber();
|
m_layersQty = m_settings->getLayersNumber();
|
||||||
m_dmxSettings = m_settings->getDmxSettings();
|
|
||||||
m_mediaLibrary = new MediaLibrary;
|
|
||||||
m_mediaLibrary->initMediaLibrary();
|
|
||||||
for (uint i = 0; i < m_layersQty; i++) {
|
for (uint i = 0; i < m_layersQty; i++) {
|
||||||
m_currentMedia[i] = "";
|
m_currentMedia[i] = "";
|
||||||
m_currentStatus[i] = Status::Iddle;
|
m_currentStatus[i] = Status::Iddle;
|
||||||
|
@ -44,6 +41,10 @@ libreMediaServerAudio::libreMediaServerAudio()
|
||||||
cout << "Can not start Audio Engine!" << endl;
|
cout << "Can not start Audio Engine!" << endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
if (m_settings->getDmxActive()) {
|
||||||
|
m_dmxSettings = m_settings->getDmxSettings();
|
||||||
|
m_mediaLibrary = new MediaLibrary;
|
||||||
|
m_mediaLibrary->initMediaLibrary();
|
||||||
m_ola = new olaThread(this, m_layersQty);
|
m_ola = new olaThread(this, m_layersQty);
|
||||||
Q_CHECK_PTR(m_ola);
|
Q_CHECK_PTR(m_ola);
|
||||||
m_ola->blockSignals(true);
|
m_ola->blockSignals(true);
|
||||||
|
@ -52,13 +53,21 @@ libreMediaServerAudio::libreMediaServerAudio()
|
||||||
m_ola->start(QThread::TimeCriticalPriority );
|
m_ola->start(QThread::TimeCriticalPriority );
|
||||||
#endif
|
#endif
|
||||||
m_ola->blockSignals(false);
|
m_ola->blockSignals(false);
|
||||||
|
} else {
|
||||||
|
qDebug() << "DMX inactive";
|
||||||
|
}
|
||||||
|
if (!m_settings->getShowPlayerActive())
|
||||||
|
qDebug() << "ShowPlayer inactive";
|
||||||
cout << "Core init Complete." << endl;
|
cout << "Core init Complete." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
libreMediaServerAudio::~libreMediaServerAudio()
|
libreMediaServerAudio::~libreMediaServerAudio()
|
||||||
{
|
{
|
||||||
|
if (m_settings->getDmxActive())
|
||||||
m_ola->stop();
|
m_ola->stop();
|
||||||
m_mae.stopEngine();
|
m_mae.stopEngine();
|
||||||
|
delete m_lmsUi;
|
||||||
|
delete m_settings;
|
||||||
sleep(1);
|
sleep(1);
|
||||||
cout << "bye!" << endl;
|
cout << "bye!" << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -139,8 +148,6 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
||||||
#ifndef NOGUI
|
#ifndef NOGUI
|
||||||
if (m_ui) {
|
if (m_ui) {
|
||||||
m_lmsUi->m_aw->filterParamChanged(layer, channel, value);
|
m_lmsUi->m_aw->filterParamChanged(layer, channel, value);
|
||||||
m_played.clear();
|
|
||||||
m_played.append(m_ola->getValue(layer, DMX_FILE));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -172,40 +179,106 @@ void libreMediaServerAudio::refreshUi() {
|
||||||
}
|
}
|
||||||
m_lmsUi->m_aw->levelChanged(i, m_mae.getLevel(i));
|
m_lmsUi->m_aw->levelChanged(i, m_mae.getLevel(i));
|
||||||
if (m_mae.getAtEnd(i)) {
|
if (m_mae.getAtEnd(i)) {
|
||||||
if (m_currentStatus[i] == Status::PlayingOnce) {
|
if (m_settings->getDmxActive())
|
||||||
|
endMediaDMX(i);
|
||||||
|
else
|
||||||
|
endMediaUi(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int libreMediaServerAudio::getFileIndexInFolder(const QString& currentFilePath) {
|
||||||
|
QDir directory = QFileInfo(currentFilePath).absoluteDir();
|
||||||
|
QStringList filters;
|
||||||
|
filters << "*.mp3" << "*.wav" << "*.flac";
|
||||||
|
QStringList fileList = directory.entryList(filters, QDir::Files, QDir::Name);
|
||||||
|
m_folderSize = fileList.size();
|
||||||
|
return fileList.indexOf(QFileInfo(currentFilePath).fileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString libreMediaServerAudio::getNextFile(const QString& currentFilePath, bool loop, bool random) {
|
||||||
|
QDir directory = QFileInfo(currentFilePath).absoluteDir();
|
||||||
|
QStringList filters;
|
||||||
|
filters << "*.mp3" << "*.wav" << "*.flac";
|
||||||
|
QStringList fileList = directory.entryList(filters, QDir::Files, QDir::Name);
|
||||||
|
m_folderSize = fileList.size();
|
||||||
|
int currentIndex = fileList.indexOf(QFileInfo(currentFilePath).fileName());
|
||||||
|
if (currentIndex >= 0 && currentIndex < m_folderSize - 1 && !random) {
|
||||||
|
return directory.absoluteFilePath(fileList.at(currentIndex + 1));
|
||||||
|
} else if (loop && fileList.size() > 0 && !random) {
|
||||||
|
return directory.absoluteFilePath(fileList.at(0));
|
||||||
|
} else if (random && m_folderSize > 0) {
|
||||||
|
if (m_played.size() >= m_folderSize )
|
||||||
|
m_played.clear();
|
||||||
|
int r = rand() % fileList.size();
|
||||||
|
while (m_played.contains(r)) {
|
||||||
|
r = rand() % fileList.size();
|
||||||
|
}
|
||||||
|
return directory.absoluteFilePath(fileList.at(r));
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudio::endMediaUi(int i)
|
||||||
|
{
|
||||||
|
QString nextFile;
|
||||||
|
if (m_currentStatus[i] == Status::PlayingOnce || m_currentStatus[i] == Status::Stopped) {
|
||||||
m_currentStatus[i] = Status::Stopped;
|
m_currentStatus[i] = Status::Stopped;
|
||||||
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
||||||
|
m_lmsUi->m_showPlayer->cueTrackAtEnd(i);
|
||||||
|
} else if (m_currentStatus[i] == Status::PlayingFolder) {
|
||||||
|
nextFile = getNextFile(m_currentMedia[i], false, false);
|
||||||
|
} else if (m_currentStatus[i] == Status::PlayingFolderLoop) {
|
||||||
|
nextFile = getNextFile(m_currentMedia[i], true, false);
|
||||||
|
} else if (m_currentStatus[i] == Status::PlayingFolderRandom) {
|
||||||
|
nextFile = getNextFile(m_currentMedia[i], false, true);
|
||||||
}
|
}
|
||||||
if (m_currentStatus[i] == Status::PlayingFolder) {
|
if (!nextFile.isEmpty()) {
|
||||||
uint last = m_played.last();
|
this->uiLoadMedia(i, nextFile);
|
||||||
|
m_mae.playbackChanged(i, m_currentStatus[i]);
|
||||||
|
} else {
|
||||||
|
m_currentStatus[i] = Status::Stopped;
|
||||||
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
||||||
|
m_lmsUi->m_showPlayer->cueTrackAtEnd(i);
|
||||||
|
m_played.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudio::endMediaDMX(int i)
|
||||||
|
{
|
||||||
|
if (m_currentStatus[i] == Status::PlayingOnce || m_currentStatus[i] == Status::Stopped) {
|
||||||
|
m_currentStatus[i] = Status::Stopped;
|
||||||
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
||||||
|
m_lmsUi->m_showPlayer->cueTrackAtEnd(i);
|
||||||
|
} else if (m_currentStatus[i] == Status::PlayingFolder) {
|
||||||
|
uint last = 0;
|
||||||
|
if (!m_played.isEmpty())
|
||||||
|
last = m_played.last() + 1;
|
||||||
int folder = m_ola->getValue(i, DMX_FOLDER);
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
||||||
last++;
|
QString nextFile = getNextFile(m_currentMedia[i], false, false);
|
||||||
if (last < m_mediaLibrary->getMediaFolderCount(folder)) {
|
if (!nextFile.isEmpty()) {
|
||||||
this->loadMedia(i, folder, last);
|
this->loadMedia(i, folder, last);
|
||||||
m_mae.playbackChanged(i, Status::PlayingFolder);
|
m_mae.playbackChanged(i, Status::PlayingFolder);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
m_currentStatus[i] = Status::Stopped;
|
m_currentStatus[i] = Status::Stopped;
|
||||||
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
||||||
|
m_lmsUi->m_showPlayer->cueTrackAtEnd(i);
|
||||||
}
|
}
|
||||||
}
|
} else if (m_currentStatus[i] == Status::PlayingFolderLoop) {
|
||||||
else if (m_currentStatus[i] == Status::PlayingFolderLoop) {
|
|
||||||
uint last = m_played.last();
|
uint last = m_played.last();
|
||||||
int folder = m_ola->getValue(i, DMX_FOLDER);
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
||||||
last++;
|
last++;
|
||||||
if (last >= m_mediaLibrary->getMediaFolderCount(folder)) {
|
QString nextFile = getNextFile(m_currentMedia[i], true, false);
|
||||||
|
if (!nextFile.isEmpty()) {
|
||||||
|
this->loadMedia(i, folder, last);
|
||||||
|
m_mae.playbackChanged(i, Status::PlayingFolder);
|
||||||
|
} else {
|
||||||
this->loadMedia(i, folder, 0);
|
this->loadMedia(i, folder, 0);
|
||||||
m_mae.playbackChanged(i, Status::PlayingFolderLoop);
|
m_mae.playbackChanged(i, Status::PlayingFolderLoop);
|
||||||
} else {
|
|
||||||
this->loadMedia(i, folder, last);
|
|
||||||
m_mae.playbackChanged(i, Status::PlayingFolder);
|
|
||||||
}
|
}
|
||||||
}
|
} else if (m_currentStatus[i] == Status::PlayingFolderRandom) {
|
||||||
else if (m_currentStatus[i] == Status::PlayingFolderRandom) {
|
|
||||||
int last = -1;
|
int last = -1;
|
||||||
int folder = m_ola->getValue(i, DMX_FOLDER);
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
||||||
if (uint(abs(m_played.size())) >= m_mediaLibrary->getMediaFolderCount(folder))
|
|
||||||
m_played.clear();
|
|
||||||
while (last == -1) {
|
while (last == -1) {
|
||||||
last = rand() % m_mediaLibrary->getMediaFolderCount(folder);
|
last = rand() % m_mediaLibrary->getMediaFolderCount(folder);
|
||||||
if (m_played.contains(last))
|
if (m_played.contains(last))
|
||||||
|
@ -215,48 +288,64 @@ void libreMediaServerAudio::refreshUi() {
|
||||||
m_mae.playbackChanged(i, Status::PlayingFolderRandom);
|
m_mae.playbackChanged(i, Status::PlayingFolderRandom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
|
void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
|
||||||
{
|
{
|
||||||
m_lmsUi = lmsUi;
|
m_lmsUi = lmsUi;
|
||||||
m_ui = true;
|
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(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int)));
|
||||||
connect(m_lmsUi->m_aw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
|
connect(m_lmsUi->m_aw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
|
||||||
connect(m_lmsUi->m_aw, SIGNAL(uiLoadMedia(int, QString)), this, SLOT(uiLoadMedia(int, QString)));
|
connect(m_lmsUi->m_aw, SIGNAL(uiLoadMedia(int, QString)), this, SLOT(uiLoadMedia(int, QString)));
|
||||||
m_refreshUi = new QTimer(this);
|
connect(m_lmsUi->m_showPlayer, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int)));
|
||||||
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
|
connect(m_lmsUi->m_showPlayer, SIGNAL(uiSliderChangedFaded(int, Slider, int, int, int)), this, SLOT(uiSliderChangedFaded(int, Slider, int, int, int)));
|
||||||
m_refreshUi->start(UI_REFRESH_TIME);
|
connect(m_lmsUi->m_showPlayer, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
|
||||||
|
connect(m_lmsUi->m_showPlayer, SIGNAL(uiLoadMedia(int, QString)), this, SLOT(uiLoadMedia(int, QString)));
|
||||||
|
if (m_settings->getDmxActive()) {
|
||||||
|
connect(m_ola, SIGNAL(universeReceived(int)), m_lmsUi->m_dmxWidget, SLOT(updateWatchDMX(int)));
|
||||||
m_ola->start(QThread::TimeCriticalPriority );
|
m_ola->start(QThread::TimeCriticalPriority );
|
||||||
|
} else {
|
||||||
|
m_lmsUi->m_dmxWidget->hide();
|
||||||
|
}
|
||||||
for (uint i = 0; i < m_settings->getAudioDeviceQty(); i++) {
|
for (uint i = 0; i < m_settings->getAudioDeviceQty(); i++) {
|
||||||
char *name = m_mae.getDeviceName(i);
|
char *name = m_mae.getDeviceName(i);
|
||||||
m_lmsUi->m_aw->busNameChanged(i, name);
|
m_lmsUi->m_aw->busNameChanged(i, name);
|
||||||
}
|
}
|
||||||
|
if (m_settings->getShowPlayerActive()) {
|
||||||
|
m_lmsUi->m_showPlayer->loadCueTrackList("lastshow.xml");
|
||||||
|
m_lmsUi->m_showPlayer->show();
|
||||||
|
}
|
||||||
|
m_refreshUi = new QTimer(this);
|
||||||
|
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
|
||||||
|
m_refreshUi->start(UI_REFRESH_TIME);
|
||||||
};
|
};
|
||||||
|
|
||||||
// From Ui widgets
|
// From Ui widgets and ShowPlayer
|
||||||
void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
|
void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
|
||||||
{
|
{
|
||||||
switch (s){
|
switch (s){
|
||||||
case Slider::Volume:
|
case Slider::Volume:
|
||||||
m_mae.volChanged(layer, value);
|
m_mae.volChanged(layer, value);
|
||||||
|
m_updateUi[layer][0] = value;
|
||||||
break;
|
break;
|
||||||
case Slider::Pan:
|
case Slider::Pan:
|
||||||
m_mae.panChanged(layer, value);
|
m_mae.panChanged(layer, value);
|
||||||
|
m_updateUi[layer][1] = value;
|
||||||
break;
|
break;
|
||||||
case Slider::Pitch:
|
case Slider::Pitch:
|
||||||
m_mae.pitchChanged(layer, value);
|
m_mae.pitchChanged(layer, value);
|
||||||
|
m_updateUi[layer][2] = value;
|
||||||
break;
|
break;
|
||||||
case Slider::Bypass:
|
case Slider::Bypass:
|
||||||
|
// ToDo: sigsev when no dmx, resolve this whitout dmxSettings, is it needed=
|
||||||
m_mae.setBypass(m_dmxSettings.at(layer).audioDevice, layer, value);
|
m_mae.setBypass(m_dmxSettings.at(layer).audioDevice, layer, value);
|
||||||
break;
|
break;
|
||||||
case Slider::Bus1:
|
case Slider::Bus1:
|
||||||
m_mae.filterParamChanged(layer, SEND1, value / 255.0f);
|
m_mae.filterParamChanged(layer, SEND1, value / 255.0f);
|
||||||
|
m_lmsUi->m_aw->filterParamChanged(layer, SEND1, value / 255.0f);
|
||||||
break;
|
break;
|
||||||
case Slider::Bus2:
|
case Slider::Bus2:
|
||||||
m_mae.filterParamChanged(layer, SEND2, value / 255.0f);
|
m_mae.filterParamChanged(layer, SEND2, value / 255.0f);
|
||||||
|
m_lmsUi->m_aw->filterParamChanged(layer, SEND2, value / 255.0f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,27 +353,59 @@ void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
|
||||||
void libreMediaServerAudio::uiPlaybackChanged(int layer, Status s)
|
void libreMediaServerAudio::uiPlaybackChanged(int layer, Status s)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
|
QString tmp;
|
||||||
|
|
||||||
result = m_mae.playbackChanged(layer, s);
|
result = m_mae.playbackChanged(layer, s);
|
||||||
if (result == MA_SUCCESS) {
|
if (result == MA_SUCCESS) {
|
||||||
m_currentStatus[layer] = s;
|
m_currentStatus[layer] = s;
|
||||||
|
m_lmsUi->m_aw->playbackChanged(layer, s);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "ui playback change error " << result << " status " << statusToString(s) << "layer" << layer;
|
qWarning() << "ui playback change error " << result << " status " << statusToString(s) << "layer" << layer;
|
||||||
}
|
}
|
||||||
|
switch (s) {
|
||||||
|
case Status::PlayingOnce:
|
||||||
|
case Status::PlayingLoop:
|
||||||
|
case Status::Iddle:
|
||||||
|
case Status::Stopped:
|
||||||
|
m_played.clear();
|
||||||
|
break;
|
||||||
|
case Status::Paused:
|
||||||
|
case Status::PlayingFolder:
|
||||||
|
case Status::PlayingFolderLoop:
|
||||||
|
break;
|
||||||
|
case Status::PlayingFolderRandom:
|
||||||
|
tmp = getNextFile(m_currentMedia[layer], false, true);
|
||||||
|
uiLoadMedia(layer, tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void libreMediaServerAudio::uiLoadMedia(int layer, QString mediaFile)
|
void libreMediaServerAudio::uiLoadMedia(int layer, QString mediaFile)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
|
|
||||||
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
|
if (mediaFile.isEmpty())
|
||||||
|
return ;
|
||||||
|
if (mediaFile.compare(m_currentMedia[layer]) == 0)
|
||||||
return;
|
return;
|
||||||
result = m_mae.loadMedia(layer, mediaFile.toLatin1().data());
|
result = m_mae.loadMedia(layer, mediaFile.toLatin1().data());
|
||||||
if (result == MA_SUCCESS) {
|
if (result == MA_SUCCESS) {
|
||||||
m_currentMedia[layer] = mediaFile;
|
m_currentMedia[layer] = mediaFile;
|
||||||
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
|
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
|
||||||
|
m_played.append(getFileIndexInFolder(mediaFile));
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "ui load media error" << result << "file" << mediaFile << "layer" << layer;
|
qWarning() << "ui load media error" << result << "file" << mediaFile << "layer" << layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudio::uiSliderChangedFaded(int layer, Slider s, int value, int fadeIn, int fadeOut)
|
||||||
|
{
|
||||||
|
switch (s){
|
||||||
|
case Slider::Volume:
|
||||||
|
m_mae.volChanged(layer, value, fadeIn, fadeOut);
|
||||||
|
m_updateUi[layer][0] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,7 @@ using namespace std;
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#ifndef NOGUI
|
#ifndef NOGUI
|
||||||
#include "libremediaserver-audio-gui.h"
|
#include "libremediaserver-audio-ui.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class libreMediaServerAudio : public QObject
|
class libreMediaServerAudio : public QObject
|
||||||
|
@ -62,12 +62,18 @@ private:
|
||||||
QTimer *m_refreshUi;
|
QTimer *m_refreshUi;
|
||||||
libreMediaServerAudioUi *m_lmsUi;
|
libreMediaServerAudioUi *m_lmsUi;
|
||||||
float m_updateUi[MAX_LAYERS][4];
|
float m_updateUi[MAX_LAYERS][4];
|
||||||
|
int m_folderSize;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void refreshUi();
|
void refreshUi();
|
||||||
void uiSliderChanged(int layer, Slider s, int value);
|
void uiSliderChanged(int layer, Slider s, int value);
|
||||||
|
void uiSliderChangedFaded(int layer, Slider s, int value, int fadeIn, int fadeOut);
|
||||||
void uiPlaybackChanged(int layer, Status s);
|
void uiPlaybackChanged(int layer, Status s);
|
||||||
void uiLoadMedia(int layer, QString s);
|
void uiLoadMedia(int layer, QString s);
|
||||||
|
void endMediaDMX(int layer);
|
||||||
|
void endMediaUi(int layer);
|
||||||
|
QString getNextFile(const QString& currentFilePath, bool loop, bool random);
|
||||||
|
int getFileIndexInFolder(const QString& currentFilePath);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,13 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
libreMediaServerAudio lms;
|
libreMediaServerAudio lms;
|
||||||
|
app.setApplicationName("LibreMediaServerAudio");
|
||||||
|
app.setOrganizationName("Criptomart");
|
||||||
|
app.setOrganizationDomain("criptomart.net");
|
||||||
|
QCoreApplication::setOrganizationName("Criptomart");
|
||||||
|
QCoreApplication::setOrganizationDomain("criptomart.net");
|
||||||
|
QCoreApplication::setApplicationName("LibreMediaServerAudio");
|
||||||
|
app.setApplicationVersion(VERSION);
|
||||||
#ifndef NOGUI
|
#ifndef NOGUI
|
||||||
if (hasUi(argc, argv) || lms.getShowUi())
|
if (hasUi(argc, argv) || lms.getShowUi())
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "olathread.h"
|
#include "olathread.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "libremediaserver-audio.h"
|
#include "libremediaserver-audio.h"
|
||||||
#include "libremediaserver-audio-gui.h"
|
#include "libremediaserver-audio-ui.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
olaThread *m_ola;
|
olaThread *m_ola;
|
||||||
|
|
81196
src/miniaudio.c
Normal file
7766
src/miniaudio.h
Normal file
|
@ -1,3 +1,4 @@
|
||||||
|
#include <QTimer>
|
||||||
#include "miniaudioengine.h"
|
#include "miniaudioengine.h"
|
||||||
#include "dmxPersonality.h"
|
#include "dmxPersonality.h"
|
||||||
|
|
||||||
|
@ -58,7 +59,9 @@ bool MiniAudioEngine::startEngine(uint layers, uint* audioDevicesId, uint audioD
|
||||||
m_mae.currentStatus[i].pitch = 128;
|
m_mae.currentStatus[i].pitch = 128;
|
||||||
m_mae.currentStatus[i].vol = 0.0f;
|
m_mae.currentStatus[i].vol = 0.0f;
|
||||||
m_mae.currentStatus[i].cursor = 0;
|
m_mae.currentStatus[i].cursor = 0;
|
||||||
m_mae.currentStatus[i].updated = false;
|
m_mae.currentStatus[i].updated = MA_FALSE;
|
||||||
|
m_mae.currentStatus[i].fadeIn = FADE_TIME;
|
||||||
|
m_mae.currentStatus[i].fadeOut = FADE_TIME;
|
||||||
}
|
}
|
||||||
result = this->startContext();
|
result = this->startContext();
|
||||||
if (result != MA_SUCCESS) return false;
|
if (result != MA_SUCCESS) return false;
|
||||||
|
@ -283,7 +286,7 @@ ma_result MiniAudioEngine::startDevices()
|
||||||
engineConfig.noAutoStart = MA_TRUE;
|
engineConfig.noAutoStart = MA_TRUE;
|
||||||
|
|
||||||
for (uint internalId = 0; internalId < m_mae.audioDevicesQty; internalId++) {
|
for (uint internalId = 0; internalId < m_mae.audioDevicesQty; internalId++) {
|
||||||
deviceConfig.capture.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id;
|
//deviceConfig.capture.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id;
|
||||||
deviceConfig.playback.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id;
|
deviceConfig.playback.pDeviceID = &m_mae.pPlaybackDeviceInfos[m_mae.audioDevicesId[internalId]].id;
|
||||||
deviceConfig.pUserData = &m_mae.engines[internalId];
|
deviceConfig.pUserData = &m_mae.engines[internalId];
|
||||||
result = ma_device_init(&m_mae.context, &deviceConfig, &m_mae.devices[internalId]);
|
result = ma_device_init(&m_mae.context, &deviceConfig, &m_mae.devices[internalId]);
|
||||||
|
@ -351,6 +354,8 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
|
|
||||||
|
if (!file || !*file)
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
if (m_mae.mediaLoaded[layer] == MA_TRUE)
|
if (m_mae.mediaLoaded[layer] == MA_TRUE)
|
||||||
{
|
{
|
||||||
m_mae.mediaLoaded[layer] = MA_FALSE;
|
m_mae.mediaLoaded[layer] = MA_FALSE;
|
||||||
|
@ -372,7 +377,7 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
m_mae.currentStatus[layer].media = file;
|
m_mae.currentStatus[layer].media = file;
|
||||||
m_mae.currentStatus[layer].updated = true;
|
m_mae.currentStatus[layer].updated = MA_TRUE;
|
||||||
m_mae.mediaLoaded[layer] = MA_TRUE;
|
m_mae.mediaLoaded[layer] = MA_TRUE;
|
||||||
this->refreshValues(layer);
|
this->refreshValues(layer);
|
||||||
return result;
|
return result;
|
||||||
|
@ -432,8 +437,18 @@ ma_result MiniAudioEngine::printFormatInfo(int layer)
|
||||||
|
|
||||||
// Expects between 0 and 65535 vol value
|
// Expects between 0 and 65535 vol value
|
||||||
void MiniAudioEngine::volChanged(int layer, int vol)
|
void MiniAudioEngine::volChanged(int layer, int vol)
|
||||||
|
{
|
||||||
|
volChanged(layer, vol, FADE_TIME, FADE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expects between 0 and 65535 vol value and fade time in milliseconds
|
||||||
|
void MiniAudioEngine::volChanged(int layer, int vol, int fadeIn, int fadeOut)
|
||||||
{
|
{
|
||||||
m_mae.currentStatus[layer].vol = vol;
|
m_mae.currentStatus[layer].vol = vol;
|
||||||
|
m_mae.currentStatus[layer].fadeIn = fadeIn;
|
||||||
|
m_mae.currentStatus[layer].fadeOut = fadeOut;
|
||||||
|
if (m_mae.mediaLoaded[layer] != MA_TRUE)
|
||||||
|
return;
|
||||||
if (m_mae.mediaLoaded[layer] == MA_FALSE && m_mae.currentStatus[layer].updated)
|
if (m_mae.mediaLoaded[layer] == MA_FALSE && m_mae.currentStatus[layer].updated)
|
||||||
return;
|
return;
|
||||||
float db = ((float)vol / 771.0f) - 85.0f;
|
float db = ((float)vol / 771.0f) - 85.0f;
|
||||||
|
@ -441,7 +456,7 @@ void MiniAudioEngine::volChanged(int layer, int vol)
|
||||||
db = 0;
|
db = 0;
|
||||||
} else
|
} else
|
||||||
db = ma_volume_db_to_linear(db);
|
db = ma_volume_db_to_linear(db);
|
||||||
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, db, FADE_TIME);
|
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], -1, db, fadeIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiniAudioEngine::panChanged(int layer, float value)
|
void MiniAudioEngine::panChanged(int layer, float value)
|
||||||
|
@ -449,7 +464,7 @@ void MiniAudioEngine::panChanged(int layer, float value)
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
m_mae.currentStatus[layer].pan = value;
|
m_mae.currentStatus[layer].pan = value;
|
||||||
if (m_mae.mediaLoaded[layer] == false)
|
if (m_mae.mediaLoaded[layer] != MA_TRUE)
|
||||||
return;
|
return;
|
||||||
result = (value / 128.0) - 1.0;
|
result = (value / 128.0) - 1.0;
|
||||||
ma_sound_group_set_pan(&m_mae.sounds[layer], result);
|
ma_sound_group_set_pan(&m_mae.sounds[layer], result);
|
||||||
|
@ -460,7 +475,7 @@ void MiniAudioEngine::pitchChanged(int layer, float value)
|
||||||
float pitch;
|
float pitch;
|
||||||
|
|
||||||
m_mae.currentStatus[layer].pitch = value;
|
m_mae.currentStatus[layer].pitch = value;
|
||||||
if (m_mae.mediaLoaded[layer] == false)
|
if (m_mae.mediaLoaded[layer] != MA_TRUE)
|
||||||
return;
|
return;
|
||||||
pitch = value / 128.0;
|
pitch = value / 128.0;
|
||||||
ma_sound_group_set_pitch(&m_mae.sounds[layer], pitch);
|
ma_sound_group_set_pitch(&m_mae.sounds[layer], pitch);
|
||||||
|
@ -471,18 +486,23 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
|
||||||
ma_result result = MA_SUCCESS;
|
ma_result result = MA_SUCCESS;
|
||||||
float db = 0;
|
float db = 0;
|
||||||
bool loop = false;
|
bool loop = false;
|
||||||
|
bool playAtBegin = false;
|
||||||
|
|
||||||
|
if (status == Status::Stopped)
|
||||||
|
playAtBegin = true;
|
||||||
m_mae.currentStatus[layer].status = status;
|
m_mae.currentStatus[layer].status = status;
|
||||||
if (m_mae.mediaLoaded[layer] == MA_FALSE)
|
if (m_mae.mediaLoaded[layer] != MA_TRUE)
|
||||||
return MA_DOES_NOT_EXIST;
|
return MA_DOES_NOT_EXIST;
|
||||||
m_mae.currentStatus[layer].updated = false;
|
m_mae.currentStatus[layer].updated = false;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Status::Paused:
|
case Status::Paused:
|
||||||
result = ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], FADE_TIME);
|
result = ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], m_mae.currentStatus[layer].fadeOut);
|
||||||
break;
|
break;
|
||||||
case Status::Stopped:
|
case Status::Stopped:
|
||||||
ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], 0.0f);
|
ma_sound_stop_with_fade_in_milliseconds(&m_mae.sounds[layer], m_mae.currentStatus[layer].fadeOut);
|
||||||
result = this->seekToCursor(layer, m_mae.currentStatus[layer].cursor);
|
QTimer::singleShot(m_mae.currentStatus[layer].fadeOut, [this, layer] {
|
||||||
|
this->seekToCursor(layer, m_mae.currentStatus[layer].cursor);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case Status::PlayingLoop:
|
case Status::PlayingLoop:
|
||||||
loop = true;
|
loop = true;
|
||||||
|
@ -493,6 +513,8 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
|
||||||
case Status::PlayingFolder:
|
case Status::PlayingFolder:
|
||||||
case Status::PlayingFolderLoop:
|
case Status::PlayingFolderLoop:
|
||||||
case Status::PlayingFolderRandom:
|
case Status::PlayingFolderRandom:
|
||||||
|
if (playAtBegin)
|
||||||
|
this->seekToCursor(layer, 0);
|
||||||
ma_sound_set_looping(&m_mae.sounds[layer], loop);
|
ma_sound_set_looping(&m_mae.sounds[layer], loop);
|
||||||
if (ma_sound_is_playing(&m_mae.sounds[layer])) break;
|
if (ma_sound_is_playing(&m_mae.sounds[layer])) break;
|
||||||
ma_sound_set_stop_time_in_milliseconds(&m_mae.sounds[layer], ~(ma_uint64)0);
|
ma_sound_set_stop_time_in_milliseconds(&m_mae.sounds[layer], ~(ma_uint64)0);
|
||||||
|
@ -502,8 +524,8 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
|
||||||
result = ma_sound_start(&m_mae.sounds[layer]);
|
result = ma_sound_start(&m_mae.sounds[layer]);
|
||||||
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], 0.000001f, 0.000000f, FADE_TIME);
|
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], 0.000001f, 0.000000f, FADE_TIME);
|
||||||
if (m_mae.currentStatus[layer].cursor > 0)
|
if (m_mae.currentStatus[layer].cursor > 0)
|
||||||
usleep(FADE_TIME * 1500); // avoid glitch when load when seeking
|
usleep(FADE_TIME * 1500); // avoid glitch when seeking
|
||||||
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], 0, db, FADE_TIME * 2);
|
ma_sound_set_fade_in_milliseconds(&m_mae.sounds[layer], 0, db, m_mae.currentStatus[layer].fadeIn);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,17 +57,14 @@ typedef struct
|
||||||
|
|
||||||
class MiniAudioEngine
|
class MiniAudioEngine
|
||||||
{
|
{
|
||||||
friend class libreMediaServerAudio;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
|
static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
|
||||||
|
|
||||||
protected:
|
|
||||||
MiniAudioEngine();
|
MiniAudioEngine();
|
||||||
void stopEngine();
|
void stopEngine();
|
||||||
bool startEngine(uint layersQty, uint* audioDevicesID, uint audioDevicesQty);
|
bool startEngine(uint layersQty, uint* audioDevicesID, uint audioDevicesQty);
|
||||||
ma_result loadMedia(int layer, char *media);
|
ma_result loadMedia(int layer, char *media);
|
||||||
void volChanged(int layer, int vol);
|
void volChanged(int layer, int vol);
|
||||||
|
void volChanged(int layer, int vol, int fadeIn, int fadeOut);
|
||||||
void panChanged(int layer, float pan);
|
void panChanged(int layer, float pan);
|
||||||
void pitchChanged(int layer, float pitch);
|
void pitchChanged(int layer, float pitch);
|
||||||
ma_result playbackChanged(int layer, Status status);
|
ma_result playbackChanged(int layer, Status status);
|
||||||
|
|
112
src/settings.cpp
|
@ -2,38 +2,131 @@
|
||||||
|
|
||||||
Settings *Settings::_instance = 0;
|
Settings *Settings::_instance = 0;
|
||||||
|
|
||||||
Settings *Settings::getInstance() {
|
Settings *Settings::getInstance(QObject *parent) {
|
||||||
|
|
||||||
if (_instance == 0) {
|
if (_instance == 0) {
|
||||||
_instance = new Settings();
|
_instance = new Settings(parent);
|
||||||
Q_CHECK_PTR(_instance);
|
Q_CHECK_PTR(_instance);
|
||||||
}
|
}
|
||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::Settings(QObject *parent) :
|
Settings::Settings(QObject *parent) :
|
||||||
QObject(parent)
|
QSettings("Criptomart", "LibreMediaServer", parent)
|
||||||
{
|
{
|
||||||
m_layersNumber = 0;
|
m_layersNumber = 0;
|
||||||
m_ui = false;
|
m_ui = false;
|
||||||
|
m_audioDeviceQty = 0;
|
||||||
|
for (uint i = 0; i < MAX_AUDIODEVICES; i++)
|
||||||
|
m_audioDeviceId[i] = -1;
|
||||||
|
if (QFile::exists(DEFAULT_FILE))
|
||||||
|
readFromFile(DEFAULT_FILE);
|
||||||
|
else if (QFile::exists(fileName()))
|
||||||
|
settingsLoader();
|
||||||
|
else {
|
||||||
|
qDebug() << "Can not read initial settings, making some standard";
|
||||||
|
setValue("lmsAudio/ui", 1);
|
||||||
|
setValue("lmsAudio/dmxActive", 0);
|
||||||
|
setValue("lmsAudio/showPlayerActive", 1);
|
||||||
|
setValue("lmsAudio/layersNumber", 2);
|
||||||
|
setValue("lmsAudio/path", "../media/");
|
||||||
|
setValue("audioDevice/devicesNumber", 2);
|
||||||
|
setValue("audioDevice/id0", 4);
|
||||||
|
setValue("audioDevice/id1", 3);
|
||||||
|
setValue("layers/layer0/dmx", 1);
|
||||||
|
setValue("layers/layer0/universe", 1);
|
||||||
|
setValue("layers/layer0/id", 0);
|
||||||
|
setValue("layers/layer0/audioDevice", 0);
|
||||||
|
setValue("layers/layer1/dmx", 26);
|
||||||
|
setValue("layers/layer1/universe", 1);
|
||||||
|
setValue("layers/layer1/id", 1);
|
||||||
|
setValue("layers/layer1/audioDevice", 0);
|
||||||
|
sync();
|
||||||
|
settingsLoader();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the dmx settings for dmx.xml At the moment we need:
|
Settings::~Settings() {
|
||||||
|
settingsSaver();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::settingsLoader()
|
||||||
|
{
|
||||||
|
qDebug() << "loading settings from system";
|
||||||
|
beginGroup("lmsAudio");
|
||||||
|
m_ui = value("ui", 0).toBool();
|
||||||
|
m_dmxActive = value("dmxActive", 0).toBool();
|
||||||
|
m_showPlayerActive = value("showPlayerActive", 0).toBool();
|
||||||
|
m_layersNumber = value("layersNumber", 0).toInt();
|
||||||
|
m_pathmedia = value("path", "").toString();
|
||||||
|
endGroup();
|
||||||
|
beginGroup("audioDevice");
|
||||||
|
m_audioDeviceQty = value("devicesNumber", 0).toInt();
|
||||||
|
for (uint i = 0; i < m_audioDeviceQty; i++)
|
||||||
|
m_audioDeviceId[i] = value(QString("id%1").arg(i), -1).toInt();
|
||||||
|
endGroup();
|
||||||
|
beginGroup("layers");
|
||||||
|
for (int i = 0; i < m_layersNumber; i++) {
|
||||||
|
beginGroup(QString("layer%1").arg(i));
|
||||||
|
dmxSetting temp;
|
||||||
|
temp.address = value("dmx", 0).toInt();
|
||||||
|
temp.universe = value("universe", 0).toInt();
|
||||||
|
temp.layer = value("id", 0).toInt();
|
||||||
|
temp.audioDevice = value("audioDevice", 0).toInt();
|
||||||
|
m_settings.append(temp);
|
||||||
|
if (!m_universe.contains(temp.universe)) {
|
||||||
|
m_universe.insert(temp.universe);
|
||||||
|
}
|
||||||
|
endGroup();
|
||||||
|
}
|
||||||
|
endGroup();
|
||||||
|
printSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::settingsSaver()
|
||||||
|
{
|
||||||
|
beginGroup("lmsAudio");
|
||||||
|
setValue("ui", m_ui);
|
||||||
|
setValue("dmxActive", m_dmxActive);
|
||||||
|
setValue("showPlayerActive", m_showPlayerActive);
|
||||||
|
setValue("layersNumber", m_layersNumber);
|
||||||
|
setValue("path", m_pathmedia);
|
||||||
|
endGroup();
|
||||||
|
beginGroup("audioDevice");
|
||||||
|
setValue("devicesNumber", m_audioDeviceQty);
|
||||||
|
for (uint i = 0; i < m_audioDeviceQty; i++)
|
||||||
|
setValue(QString("id%1").arg(i), m_audioDeviceId[i]);
|
||||||
|
endGroup();
|
||||||
|
beginGroup("layers");
|
||||||
|
for (int i = 0; i < m_layersNumber; i++) {
|
||||||
|
beginGroup(QString("layer%1").arg(i));
|
||||||
|
setValue("dmx", m_settings[i].address);
|
||||||
|
setValue("universe", m_settings[i].universe);
|
||||||
|
setValue("id", m_settings[i].layer);
|
||||||
|
setValue("audioDevice", m_settings[i].audioDevice);
|
||||||
|
endGroup();
|
||||||
|
}
|
||||||
|
endGroup();
|
||||||
|
sync();
|
||||||
|
qDebug() << "writed settings to " << fileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the dmx settings. At the moment we need:
|
||||||
// - The path to the medias folder tree
|
// - The path to the medias folder tree
|
||||||
// - The number of sources/layers controlled by DMX
|
// - The number of sources/layers controlled by DMX
|
||||||
// - The first DMX channel of each source/layer
|
// - The first DMX channel of each source/layer
|
||||||
// - The universe to bind in OLA
|
// - dmxActive and The universe to bind in OLA
|
||||||
// - Audio device id
|
// - Audio device id
|
||||||
// - Show the Ui or not
|
// - Show Ui, showPlayer
|
||||||
void Settings::readFromFile(QString file) {
|
void Settings::readFromFile(QString file) {
|
||||||
|
qDebug() << "loading settings from xml file " << file;
|
||||||
QFile* xmlFile = new QFile(file);
|
QFile* xmlFile = new QFile(file);
|
||||||
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
QMessageBox::critical(NULL,"Load XML File Problem",
|
QMessageBox::critical(NULL,"Load XML File Problem",
|
||||||
QString("Couldn't open %1 to load settings").arg(file),
|
QString("Couldn't open %1 to load settings").arg(file),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
// Instead exit give the oportunity to load another file or define the settings
|
|
||||||
qCritical("Load XML File Problem");
|
qCritical("Load XML File Problem");
|
||||||
exit(1);
|
return;
|
||||||
}
|
}
|
||||||
QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile);
|
QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile);
|
||||||
while(!xmlReader->atEnd() && !xmlReader->hasError()) {
|
while(!xmlReader->atEnd() && !xmlReader->hasError()) {
|
||||||
|
@ -44,6 +137,8 @@ void Settings::readFromFile(QString file) {
|
||||||
if(token == QXmlStreamReader::StartElement) {
|
if(token == QXmlStreamReader::StartElement) {
|
||||||
if(xmlReader->name() == "lmsAudio") {
|
if(xmlReader->name() == "lmsAudio") {
|
||||||
m_ui = xmlReader->attributes().value("ui").toLocal8Bit().toInt();
|
m_ui = xmlReader->attributes().value("ui").toLocal8Bit().toInt();
|
||||||
|
m_dmxActive = xmlReader->attributes().value("dmxActive").toInt();
|
||||||
|
m_showPlayerActive = xmlReader->attributes().value("showPlayerActive").toInt();
|
||||||
m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
|
m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
|
||||||
m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
|
m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
|
||||||
continue;
|
continue;
|
||||||
|
@ -80,6 +175,7 @@ void Settings::readFromFile(QString file) {
|
||||||
|
|
||||||
void Settings::printSettings() {
|
void Settings::printSettings() {
|
||||||
qInfo() << "Settings readed:\nShow Ui:" << m_ui << "Layers:" << m_layersNumber << "Path:" << m_pathmedia <<"Audio Device qty:" << m_audioDeviceQty;
|
qInfo() << "Settings readed:\nShow Ui:" << m_ui << "Layers:" << m_layersNumber << "Path:" << m_pathmedia <<"Audio Device qty:" << m_audioDeviceQty;
|
||||||
|
qInfo() << "dmx: " << m_dmxActive << " showPlayer: " << m_showPlayerActive;
|
||||||
for (uint i = 0; i < m_audioDeviceQty; i++)
|
for (uint i = 0; i < m_audioDeviceQty; i++)
|
||||||
qInfo() << "Audio device internal id:" << i << "system id:" << m_audioDeviceId[i];
|
qInfo() << "Audio device internal id:" << i << "system id:" << m_audioDeviceId[i];
|
||||||
for (int i = 0; i < m_layersNumber; i++)
|
for (int i = 0; i < m_layersNumber; i++)
|
||||||
|
|
|
@ -6,28 +6,35 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
#include "medialibrary.h"
|
#include "medialibrary.h"
|
||||||
#include "audiowidget.h"
|
#include "audiowidget.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
class Settings : public QObject
|
class Settings : public QSettings
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Settings(QObject *parent = 0);
|
Settings(QObject *parent = nullptr);
|
||||||
static Settings *getInstance();
|
~Settings();
|
||||||
|
static Settings *getInstance(QObject *parent = nullptr);
|
||||||
inline QSet<int> getUniverses() { return m_universe; }
|
inline QSet<int> getUniverses() { return m_universe; }
|
||||||
inline QString getPathMedia() { return m_pathmedia; }
|
inline QString getPathMedia() { return m_pathmedia; }
|
||||||
|
inline void setPathMedia(QString new_path) { m_pathmedia = new_path; };
|
||||||
inline QList<dmxSetting> getDmxSettings() { return m_settings; }
|
inline QList<dmxSetting> getDmxSettings() { return m_settings; }
|
||||||
inline int getLayersNumber() { return m_layersNumber; }
|
inline int getLayersNumber() { return m_layersNumber; }
|
||||||
inline uint *getAudioDeviceId() { return m_audioDeviceId; }
|
inline uint *getAudioDeviceId() { return m_audioDeviceId; }
|
||||||
inline uint getAudioDeviceQty() { return m_audioDeviceQty; }
|
inline uint getAudioDeviceQty() { return m_audioDeviceQty; }
|
||||||
inline bool getShowUi() { return m_ui; }
|
inline bool getShowUi() { return m_ui; }
|
||||||
|
inline bool getDmxActive() { return m_dmxActive; }
|
||||||
|
inline bool getShowPlayerActive() { return m_showPlayerActive; }
|
||||||
void readFile();
|
void readFile();
|
||||||
void readFromFile(QString file);
|
void readFromFile(QString file);
|
||||||
void printSettings();
|
void printSettings();
|
||||||
|
void settingsLoader();
|
||||||
|
void settingsSaver();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Settings *_instance;
|
static Settings *_instance;
|
||||||
|
@ -38,6 +45,8 @@ private:
|
||||||
QSet<int> m_universe;
|
QSet<int> m_universe;
|
||||||
int m_layersNumber;
|
int m_layersNumber;
|
||||||
bool m_ui;
|
bool m_ui;
|
||||||
|
bool m_dmxActive;
|
||||||
|
bool m_showPlayerActive;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
|
223
src/showplayer.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
#include "showplayer.h"
|
||||||
|
|
||||||
|
|
||||||
|
ShowPlayer::ShowPlayer(QWidget *parent) :
|
||||||
|
QDialog(parent, Qt::Window)
|
||||||
|
, ui(new Ui::ShowPlayer)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
connect(ui->NewCue, SIGNAL(clicked()), this, SLOT(onAddTrack()));
|
||||||
|
connect(ui->EditCue, SIGNAL(clicked()), ui->cueListWidget, SLOT(editCueTrack()));
|
||||||
|
connect(ui->RemoveCue, SIGNAL(clicked()), ui->cueListWidget, SLOT(deleteCueTrack()));
|
||||||
|
connect(ui->SaveCueList, SIGNAL(clicked()), this, SLOT(saveCueTrackList()));
|
||||||
|
connect(ui->LoadCueList, SIGNAL(clicked()), this, SLOT(loadCueTrackList()));
|
||||||
|
connect(ui->goButton, SIGNAL(clicked()), this, SLOT(go()));
|
||||||
|
connect(ui->cueListWidget, SIGNAL(changeSelectedIndex(int)), this, SLOT(updateIndex(int)));
|
||||||
|
connect(ui->panicButton, SIGNAL(clicked()), this, SLOT(panicButtonClicked()));
|
||||||
|
connect(ui->restoreButton, SIGNAL(clicked()), this, SLOT(restoreButtonClicked()));
|
||||||
|
connect(ui->CopyCue, SIGNAL(clicked()), ui->cueListWidget, SLOT(copyCueTrack()));
|
||||||
|
connect(ui->PasteCue, SIGNAL(clicked()), ui->cueListWidget, SLOT(pasteCueTrack()));
|
||||||
|
connect(ui->CutCue, SIGNAL(clicked()), ui->cueListWidget, SLOT(cutCueTrack()));
|
||||||
|
currentStatus = Status::Iddle;
|
||||||
|
for(int i = 0; i < MAX_LAYERS; i++) {
|
||||||
|
layersUsed[i] = -1;
|
||||||
|
cueTrackWidgetPlaying[i] = nullptr;
|
||||||
|
current[i] = nullptr;
|
||||||
|
prevCue[i] = nullptr;
|
||||||
|
}
|
||||||
|
ui->nextCue->setNextCue();
|
||||||
|
Settings::getInstance()->beginGroup("showPlayerSplittersState");
|
||||||
|
ui->splitter_main->restoreState(Settings::getInstance()->value("mainSplitter").toByteArray());
|
||||||
|
ui->splitter_controls->restoreState(Settings::getInstance()->value("controlsSplitter").toByteArray());
|
||||||
|
ui->splitter_cues->restoreState(Settings::getInstance()->value("cueSplitter").toByteArray());
|
||||||
|
Settings::getInstance()->endGroup();
|
||||||
|
ui->activeCueList->setSelectionMode(QAbstractItemView::NoSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowPlayer::~ShowPlayer()
|
||||||
|
{
|
||||||
|
saveCueTrackList("lastshow.xml");
|
||||||
|
Settings::getInstance()->beginGroup("showPlayerSplittersState");
|
||||||
|
Settings::getInstance()->setValue("mainSplitter", ui->splitter_main->saveState());
|
||||||
|
Settings::getInstance()->setValue("controlsSplitter", ui->splitter_controls->saveState());
|
||||||
|
Settings::getInstance()->setValue("cueSplitter", ui->splitter_cues->saveState());
|
||||||
|
Settings::getInstance()->endGroup();
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::onAddTrack() {
|
||||||
|
ui->cueListWidget->createNewCueTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::go()
|
||||||
|
{
|
||||||
|
CueTrack *goCue = ui->cueListWidget->getSelectedTrack(true);
|
||||||
|
if (!goCue)
|
||||||
|
return;
|
||||||
|
prevCue[goCue->audioLayer] = current[goCue->audioLayer];
|
||||||
|
current[goCue->audioLayer] = goCue;
|
||||||
|
removeCueTrackWidget(goCue->audioLayer);
|
||||||
|
CueTrackWidget *widget = addCueTrackWidget(goCue);
|
||||||
|
widget->go();
|
||||||
|
if (goCue->multi)
|
||||||
|
go();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::goAction(int c)
|
||||||
|
{
|
||||||
|
if (!current[c]->filePath.empty()) {
|
||||||
|
emit uiLoadMedia(current[c]->audioLayer, current[c]->filePath.data());
|
||||||
|
ui->cueListWidget->cueTrackAtEnd(c);
|
||||||
|
}
|
||||||
|
updateTrackStateInEngine(current[c]);
|
||||||
|
emit uiPlaybackChanged(current[c]->audioLayer, current[c]->status);
|
||||||
|
switch (current[c]->status) {
|
||||||
|
case Status::PlayingOnce:
|
||||||
|
case Status::PlayingLoop:
|
||||||
|
case Status::PlayingFolder:
|
||||||
|
case Status::PlayingFolderLoop:
|
||||||
|
case Status::PlayingFolderRandom:
|
||||||
|
current[c]->active = true;
|
||||||
|
layersUsed[current[c]->audioLayer] = current[c]->userNumber;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
current[c]->active = false;
|
||||||
|
}
|
||||||
|
ui->cueListWidget->redrawCueTrackList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::fade(Slider s, int start, CueTrack *track) {
|
||||||
|
AudioFade *fade = new AudioFade(s, start, track, this);
|
||||||
|
connect(fade, SIGNAL(uiSliderChanged(int, Slider, int)), this, SIGNAL(uiSliderChanged(int, Slider, int)));
|
||||||
|
fade->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::updateTrackStateInEngine(CueTrack *track) {
|
||||||
|
emit uiSliderChangedFaded(track->audioLayer, Slider::Volume, track->volume * 655.35, track->fadeIn * 1000, track->fadeOut * 1000);
|
||||||
|
if (track->fadeIn != 0 && prevCue[track->audioLayer] != nullptr) {
|
||||||
|
if (prevCue[track->audioLayer]->pan != track->pan)
|
||||||
|
fade(Slider::Pan, prevCue[track->audioLayer]->pan, track);
|
||||||
|
if (prevCue[track->audioLayer]->pitch != track->pitch)
|
||||||
|
fade(Slider::Pitch, prevCue[track->audioLayer]->pitch, track);
|
||||||
|
if (prevCue[track->audioLayer]->bus1 != track->bus1)
|
||||||
|
fade(Slider::Bus1, prevCue[track->audioLayer]->bus1, track);
|
||||||
|
if (prevCue[track->audioLayer]->bus2 != track->bus2)
|
||||||
|
fade(Slider::Bus2, prevCue[track->audioLayer]->bus2, track);
|
||||||
|
} else {
|
||||||
|
emit uiSliderChanged(track->audioLayer, Slider::Pan, (track->pan + 1) * 128);
|
||||||
|
emit uiSliderChanged(track->audioLayer, Slider::Pitch, track->pitch * 128);
|
||||||
|
emit uiSliderChanged(track->audioLayer, Slider::Bus1, track->bus1 * 255 * 2.55);
|
||||||
|
emit uiSliderChanged(track->audioLayer, Slider::Bus2, track->bus2 * 255 * 2.55);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::loadCueTrackList()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("XML Files (*.xml)"));
|
||||||
|
if (fileName.isEmpty())
|
||||||
|
return;
|
||||||
|
ui->cueListWidget->loadCueTrackList(fileName.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::saveCueTrackList()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("XML Files (*.xml)"));
|
||||||
|
if (fileName.isEmpty())
|
||||||
|
return;
|
||||||
|
ui->cueListWidget->saveCueTrackList(fileName.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::cueTrackAtEnd(int layer)
|
||||||
|
{
|
||||||
|
current[layer]->active = false;
|
||||||
|
ui->cueListWidget->cueTrackAtEnd(layer);
|
||||||
|
removeCueTrackWidget(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::cueFinished(int c)
|
||||||
|
{
|
||||||
|
if (!current[c])
|
||||||
|
return;
|
||||||
|
if (!current[c]->stopAtEnd)
|
||||||
|
this->go();
|
||||||
|
if (current[c]->status == Status::Stopped || current[c]->status == Status::Paused)
|
||||||
|
cueTrackAtEnd(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
CueTrackWidget *ShowPlayer::addCueTrackWidget(CueTrack* track) {
|
||||||
|
QListWidgetItem* item = new QListWidgetItem(ui->activeCueList);
|
||||||
|
CueTrackWidget* widget = new CueTrackWidget();
|
||||||
|
widget->loadCueTrack(track);
|
||||||
|
connect(widget, SIGNAL(goAction(int)), this, SLOT(goAction(int)));
|
||||||
|
connect(widget, SIGNAL(cueFinished(int)), this, SLOT(cueFinished(int)));
|
||||||
|
connect(widget, SIGNAL(changeStatus(int, Status)), this, SIGNAL(uiPlaybackChanged(int, Status)));
|
||||||
|
connect(widget, SIGNAL(changeVol(int, Slider, int, int, int)), this, SIGNAL(uiSliderChangedFaded(int, Slider, int, int, int)));
|
||||||
|
cueTrackWidgetPlaying[track->audioLayer] = widget;
|
||||||
|
item->setSizeHint(widget->sizeHint());
|
||||||
|
ui->activeCueList->setItemWidget(item, widget);
|
||||||
|
return (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::playCueTrack(CueTrack* track) {
|
||||||
|
removeCueTrackWidget(track->audioLayer);
|
||||||
|
CueTrackWidget *widget = addCueTrackWidget(track);
|
||||||
|
widget->go();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::removeCueTrackWidget(int audioLayer) {
|
||||||
|
CueTrackWidget* widgetToRemove = cueTrackWidgetPlaying[audioLayer];
|
||||||
|
if (widgetToRemove != NULL && ui->activeCueList->count() > 0) {
|
||||||
|
for (int i = 0; i < ui->activeCueList->count(); ++i) {
|
||||||
|
QListWidgetItem* item = ui->activeCueList->item(i);
|
||||||
|
QWidget* widget = ui->activeCueList->itemWidget(item);
|
||||||
|
if (widget == widgetToRemove) {
|
||||||
|
ui->activeCueList->removeItemWidget(item);
|
||||||
|
delete item;
|
||||||
|
delete widgetToRemove;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cueTrackWidgetPlaying[audioLayer] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::updateIndex(int index) {
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
CueTrack *track = ui->cueListWidget->getSelectedTrack(false);
|
||||||
|
if (track) {
|
||||||
|
ui->nextCue->loadCueTrack(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::loadCueTrackList(QString path) {
|
||||||
|
ui->cueListWidget->loadCueTrackList(path.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::saveCueTrackList(QString path) {
|
||||||
|
ui->cueListWidget->saveCueTrackList(path.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::panicButtonClicked() {
|
||||||
|
for (int i = 0; i < MAX_LAYERS; i++) {
|
||||||
|
if (layersUsed[i] != -1) {
|
||||||
|
CueTrack* track = current[i];
|
||||||
|
if (track && track->active) {
|
||||||
|
emit uiSliderChanged(track->audioLayer, Slider::Volume, 0);
|
||||||
|
emit uiPlaybackChanged(track->audioLayer, Status::Paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPlayer::restoreButtonClicked() {
|
||||||
|
for (int i = 0; i < MAX_LAYERS; i++) {
|
||||||
|
if (layersUsed[i] != -1) {
|
||||||
|
CueTrack* track = current[i];
|
||||||
|
if (track) {
|
||||||
|
emit uiSliderChangedFaded(track->audioLayer, Slider::Volume, track->volume * 655.35, track->fadeIn, track->fadeOut);
|
||||||
|
emit uiPlaybackChanged(track->audioLayer, track->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
src/showplayer.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef SHOWPLAYER_H
|
||||||
|
#define SHOWPLAYER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "cuetracklistwidget.h"
|
||||||
|
#include "cuetrackwidget.h"
|
||||||
|
#include "dialgroup.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "audiofade.h"
|
||||||
|
#include "ui_showplayer.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ShowPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowPlayer : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ShowPlayer(QWidget *parent = nullptr);
|
||||||
|
~ShowPlayer();
|
||||||
|
Ui::ShowPlayer *ui;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void cueTrackAtEnd(int layer);
|
||||||
|
void loadCueTrackList(QString path);
|
||||||
|
void saveCueTrackList(QString path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Status currentStatus = Status::Iddle;
|
||||||
|
int layersUsed[MAX_LAYERS];
|
||||||
|
CueTrack *current[MAX_LAYERS];
|
||||||
|
CueTrack *prevCue[MAX_LAYERS];
|
||||||
|
CueTrackWidget *cueTrackWidgetPlaying[MAX_LAYERS];
|
||||||
|
CueTrackWidget *addCueTrackWidget(CueTrack *track);
|
||||||
|
std::map<int, std::pair<Status, double>> prePanicState;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateTrackStateInEngine(CueTrack *track);
|
||||||
|
void onAddTrack();
|
||||||
|
void go();
|
||||||
|
void loadCueTrackList();
|
||||||
|
void saveCueTrackList();
|
||||||
|
void cueFinished(int channel);
|
||||||
|
void removeCueTrackWidget(int index);
|
||||||
|
void playCueTrack(CueTrack *track);
|
||||||
|
void goAction(int channel);
|
||||||
|
void updateIndex(int index);
|
||||||
|
void fade(Slider s, int start, CueTrack *track);
|
||||||
|
void panicButtonClicked();
|
||||||
|
void restoreButtonClicked();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void uiPlaybackChanged(int layer, Status s);
|
||||||
|
void uiSliderChanged(int layer, Slider s, int value);
|
||||||
|
void uiSliderChangedFaded(int layer, Slider s, int value, int fadeIn, int fadeOut);
|
||||||
|
void uiLoadMedia(int layer, QString s);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHOWPLAYER_H
|
385
src/showplayer.ui
Normal file
|
@ -0,0 +1,385 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ShowPlayer</class>
|
||||||
|
<widget class="QDialog" name="ShowPlayer">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>802</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Show Player</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/icon.png</normaloff>:/buttons/resources/icon.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="splitter_main">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||||
|
<layout class="QHBoxLayout" name="ButtonToolBarLayout" stretch="0,0,0,0,0,0,0,0">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="LoadCueList">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Load Cue List</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Load CueList</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/load_button.png</normaloff>:/buttons/resources/load_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="SaveCueList">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Save Cue List</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save CueList.</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/save_button.png</normaloff>:/buttons/resources/save_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="CopyCue">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>32</horstretch>
|
||||||
|
<verstretch>32</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Copy Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/copy_button.png</normaloff>:/buttons/resources/copy_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="CutCue">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Cut Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Load Cue List</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Cut Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/cut_button.png</normaloff>:/buttons/resources/cut_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="PasteCue">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Paste Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Paste Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/paste_button.png</normaloff>:/buttons/resources/paste_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="NewCue">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>New Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/new_button.png</normaloff>:/buttons/resources/new_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="EditCue">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Edit Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Edit Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/edit_button.png</normaloff>:/buttons/resources/edit_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="RemoveCue">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete Cue</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/delete_button.png</normaloff>:/buttons/resources/delete_button.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSplitter" name="splitter_controls">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QPushButton" name="goButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/go_button.jpeg</normaloff>:/buttons/resources/go_button.jpeg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>120</width>
|
||||||
|
<height>120</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Space</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoDefault">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="CueTrackWidget" name="nextCue" native="true"/>
|
||||||
|
<widget class="QToolButton" name="panicButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Panic!</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/panic_button.jpg</normaloff>:/buttons/resources/panic_button.jpg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>120</width>
|
||||||
|
<height>120</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>P</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="restoreButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Restore</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../lms-resources.qrc">
|
||||||
|
<normaloff>:/buttons/resources/restore_button.jpg</normaloff>:/buttons/resources/restore_button.jpg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>120</width>
|
||||||
|
<height>120</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSplitter" name="splitter_cues">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="CueTrackListWidget" name="cueListWidget" native="true">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Cue List</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QListWidget" name="activeCueList">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Cues active</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="resizeMode">
|
||||||
|
<enum>QListView::Adjust</enum>
|
||||||
|
</property>
|
||||||
|
<property name="layoutMode">
|
||||||
|
<enum>QListView::SinglePass</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CueTrackListWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>src/cuetracklistwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CueTrackWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>src/cuetrackwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>NewCue</tabstop>
|
||||||
|
<tabstop>EditCue</tabstop>
|
||||||
|
<tabstop>RemoveCue</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources>
|
||||||
|
<include location="../lms-resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -38,16 +38,16 @@ SliderGroup::SliderGroup(QString name,
|
||||||
"margin: 0px;}"
|
"margin: 0px;}"
|
||||||
"QSlider::groove:vertical {"
|
"QSlider::groove:vertical {"
|
||||||
"border: 1px solid #999999;"
|
"border: 1px solid #999999;"
|
||||||
"width: 25px;"
|
"width: 25px;}"
|
||||||
"margin: -4px;}"
|
|
||||||
"QSlider::handle:vertical {"
|
"QSlider::handle:vertical {"
|
||||||
"background: white;"
|
"background: white;"
|
||||||
"border: 1px solid #5c5c5c;"
|
"border: 2px solid #5c5c5c;"
|
||||||
"width: 29px;"
|
"width: 29px;"
|
||||||
"height: 7px;"
|
"height: 10px;"
|
||||||
"margin: -2px;"
|
|
||||||
"border-radius: 2px;}"
|
"border-radius: 2px;}"
|
||||||
"Qslider::tickmarks:vertical {background: white;"
|
"Qslider::tickmarks:vertical {"
|
||||||
|
"background-color: black;"
|
||||||
|
"background: red;"
|
||||||
"color: white;}"
|
"color: white;}"
|
||||||
"QSlider::add-page:vertical {background: blue;}"
|
"QSlider::add-page:vertical {background: blue;}"
|
||||||
"QSlider::sub-page:vertical {background: #20182d;}");
|
"QSlider::sub-page:vertical {background: #20182d;}");
|
||||||
|
|