293 lines
11 KiB
C++
293 lines
11 KiB
C++
/*
|
|
|
|
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.h"
|
|
|
|
|
|
libreMediaServerAudio::libreMediaServerAudio()
|
|
{
|
|
m_settings = Settings::getInstance();
|
|
m_settings->readFile();
|
|
m_ui = m_settings->getShowUi();
|
|
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++) {
|
|
m_currentMedia[i] = "";
|
|
m_currentStatus[i] = Status::Iddle;
|
|
#ifdef NOGUI
|
|
m_updateUi[i][0] = -1;
|
|
m_updateUi[i][1] = -1;
|
|
m_updateUi[i][2] = -1;
|
|
m_updateUi[i][3] = -1;
|
|
#endif
|
|
}
|
|
if (!m_mae.startEngine(m_layersQty, m_settings->getAudioDeviceId(), m_settings->getAudioDeviceQty())) {
|
|
cout << "Can not start Audio Engine!" << endl;
|
|
exit(-1);
|
|
}
|
|
m_ola = new olaThread(this, m_layersQty);
|
|
Q_CHECK_PTR(m_ola);
|
|
m_ola->blockSignals(true);
|
|
m_ola->registerUniverse();
|
|
#ifdef NOGUI
|
|
m_ola->start(QThread::TimeCriticalPriority );
|
|
#endif
|
|
m_ola->blockSignals(false);
|
|
cout << "Core init Complete." << endl;
|
|
}
|
|
|
|
libreMediaServerAudio::~libreMediaServerAudio()
|
|
{
|
|
m_ola->stop();
|
|
m_mae.stopEngine();
|
|
sleep(1);
|
|
cout << "bye!" << endl;
|
|
exit(0);
|
|
}
|
|
|
|
void libreMediaServerAudio::loadMedia(int layer, int folder, int file)
|
|
{
|
|
QString mediaFile = m_mediaLibrary->requestNewFile(folder, file);
|
|
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
|
|
return;
|
|
if (QFile::exists(mediaFile)){
|
|
m_mae.loadMedia(layer, mediaFile.toLatin1().data());
|
|
m_currentMedia[layer] = mediaFile;
|
|
#ifndef NOGUI
|
|
if (m_ui)
|
|
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
|
|
#endif
|
|
m_mae.printFormatInfo(layer);
|
|
}
|
|
if (m_currentStatus[layer] == Status::PlayingFolder \
|
|
|| (m_currentStatus[layer] == Status::PlayingFolderLoop)\
|
|
|| (m_currentStatus[layer] == Status::PlayingFolderRandom)) {
|
|
m_played.append(file);
|
|
} else if (m_currentStatus[layer] == Status::PlayingOnce \
|
|
|| m_currentStatus[layer] == Status::PlayingLoop) {
|
|
m_played.clear();
|
|
}
|
|
}
|
|
|
|
void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
|
{
|
|
if (layer >= MAX_LAYERS || channel >= LAYER_CHANNELS)
|
|
return;
|
|
QString mediaFile = NULL;
|
|
int aux;
|
|
if (channel == VOLUME_COARSE || channel == VOLUME_FINE) {
|
|
m_mae.volChanged(layer, value);
|
|
m_updateUi[layer][0] = value;
|
|
} else if (channel == PAN) {
|
|
m_mae.panChanged(layer, value);
|
|
m_updateUi[layer][1] = value;
|
|
} else if (channel == PITCH) {
|
|
m_mae.pitchChanged(layer, value);
|
|
m_updateUi[layer][2] = value;
|
|
} else if (channel == ENTRY_POINT_COARSE || channel == ENTRY_POINT_FINE) {
|
|
m_mae.setCursor(layer, value);
|
|
m_updateUi[layer][3] = value;
|
|
} else if (channel == PLAYBACK && value > 0) {
|
|
aux = value / 25;
|
|
Status s = m_currentStatus[layer];
|
|
if (aux == 0)
|
|
s = Status::PlayingOnce;
|
|
else if (aux == 1)
|
|
s = Status::Stopped;
|
|
else if (aux == 2)
|
|
s = Status::Paused;
|
|
else if (aux == 3)
|
|
s = Status::PlayingLoop;
|
|
else if (aux == 4)
|
|
s = Status::PlayingFolder;
|
|
else if (aux == 5)
|
|
s = Status::PlayingFolderLoop;
|
|
else if (aux == 6)
|
|
s = Status::PlayingFolderRandom;
|
|
m_mae.playbackChanged(layer, s);
|
|
m_currentStatus[layer] = s;
|
|
qInfo() << "Layer" << layer << statusToString(s);
|
|
#ifndef NOGUI
|
|
if (m_ui) {
|
|
m_lmsUi->m_aw->playbackChanged(layer, s);
|
|
m_updateUi[layer][3] = 1;
|
|
m_played.clear();
|
|
m_played.append(m_ola->getValue(layer, DMX_FILE));
|
|
}
|
|
#endif
|
|
} else if (channel >= HP_FREQ) {
|
|
m_mae.filterParamChanged(layer, channel, value);
|
|
#ifndef NOGUI
|
|
if (m_ui) {
|
|
m_lmsUi->m_aw->filterParamChanged(layer, channel, value);
|
|
m_played.clear();
|
|
m_played.append(m_ola->getValue(layer, DMX_FILE));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#ifndef NOGUI
|
|
void libreMediaServerAudio::refreshUi() {
|
|
if (!m_ui) return;
|
|
for (int i= 0; i < m_settings->getLayersNumber(); i++ ) {
|
|
if (m_updateUi[i][0] >= 0) {
|
|
m_lmsUi->m_aw->volChanged(i, m_updateUi[i][0]);
|
|
m_updateUi[i][0] = -1;
|
|
}
|
|
if (m_updateUi[i][1] >= 0) {
|
|
m_lmsUi->m_aw->panChanged(i, m_updateUi[i][1]);
|
|
m_updateUi[i][1] = -1;
|
|
}
|
|
if (m_updateUi[i][2] >= 0) {
|
|
m_lmsUi->m_aw->pitchChanged(i, m_updateUi[i][2]);
|
|
m_updateUi[i][2] = -1;
|
|
}
|
|
if (m_updateUi[i][3] >= 0 \
|
|
|| m_currentStatus[i] == Status::PlayingOnce\
|
|
|| m_currentStatus[i] == Status::PlayingLoop\
|
|
|| m_currentStatus[i] == Status::PlayingFolder\
|
|
|| m_currentStatus[i] == Status::PlayingFolderLoop
|
|
|| m_currentStatus[i] == Status::PlayingFolderRandom) {
|
|
m_lmsUi->m_aw->cursorChanged(i, m_mae.getCursor(i));
|
|
m_updateUi[i][3] = -1;
|
|
}
|
|
m_lmsUi->m_aw->levelChanged(i, m_mae.getLevel(i));
|
|
if (m_mae.getAtEnd(i)) {
|
|
if (m_currentStatus[i] == Status::PlayingOnce) {
|
|
m_currentStatus[i] = Status::Stopped;
|
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
|
}
|
|
if (m_currentStatus[i] == Status::PlayingFolder) {
|
|
uint last = m_played.last();
|
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
|
last++;
|
|
if (last < m_mediaLibrary->getMediaFolderCount(folder)) {
|
|
this->loadMedia(i, folder, last);
|
|
m_mae.playbackChanged(i, Status::PlayingFolder);
|
|
}
|
|
else {
|
|
m_currentStatus[i] = Status::Stopped;
|
|
m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
|
|
}
|
|
}
|
|
else if (m_currentStatus[i] == Status::PlayingFolderLoop) {
|
|
uint last = m_played.last();
|
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
|
last++;
|
|
if (last >= m_mediaLibrary->getMediaFolderCount(folder)) {
|
|
this->loadMedia(i, folder, 0);
|
|
m_mae.playbackChanged(i, Status::PlayingFolderLoop);
|
|
} else {
|
|
this->loadMedia(i, folder, last);
|
|
m_mae.playbackChanged(i, Status::PlayingFolder);
|
|
}
|
|
}
|
|
else if (m_currentStatus[i] == Status::PlayingFolderRandom) {
|
|
int last = -1;
|
|
int folder = m_ola->getValue(i, DMX_FOLDER);
|
|
if (uint(abs(m_played.size())) >= m_mediaLibrary->getMediaFolderCount(folder))
|
|
m_played.clear();
|
|
while (last == -1) {
|
|
last = rand() % m_mediaLibrary->getMediaFolderCount(folder);
|
|
if (m_played.contains(last))
|
|
last = -1;
|
|
}
|
|
this->loadMedia(i, folder, last);
|
|
m_mae.playbackChanged(i, Status::PlayingFolderRandom);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
|
|
{
|
|
m_lmsUi = lmsUi;
|
|
m_ui = true;
|
|
connect(m_ola, SIGNAL(universeReceived(int)), m_lmsUi->m_dmxWidget, SLOT(updateWatchDMX(int)));
|
|
connect(m_lmsUi->m_aw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int)));
|
|
connect(m_lmsUi->m_aw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
|
|
connect(m_lmsUi->m_aw, SIGNAL(uiLoadMedia(int, QString)), this, SLOT(uiLoadMedia(int, QString)));
|
|
connect(m_lmsUi->m_showPlayer, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int)));
|
|
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)));
|
|
m_refreshUi = new QTimer(this);
|
|
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
|
|
m_refreshUi->start(UI_REFRESH_TIME);
|
|
m_ola->start(QThread::TimeCriticalPriority );
|
|
for (uint i = 0; i < m_settings->getAudioDeviceQty(); i++) {
|
|
char *name = m_mae.getDeviceName(i);
|
|
m_lmsUi->m_aw->busNameChanged(i, name);
|
|
}
|
|
};
|
|
|
|
// From Ui widgets and ShowPlayer
|
|
void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
|
|
{
|
|
switch (s){
|
|
case Slider::Volume:
|
|
m_mae.volChanged(layer, value);
|
|
break;
|
|
case Slider::Pan:
|
|
m_mae.panChanged(layer, value);
|
|
break;
|
|
case Slider::Pitch:
|
|
m_mae.pitchChanged(layer, value);
|
|
break;
|
|
case Slider::Bypass:
|
|
m_mae.setBypass(m_dmxSettings.at(layer).audioDevice, layer, value);
|
|
break;
|
|
case Slider::Bus1:
|
|
m_mae.filterParamChanged(layer, SEND1, value / 255.0f);
|
|
break;
|
|
case Slider::Bus2:
|
|
m_mae.filterParamChanged(layer, SEND2, value / 255.0f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void libreMediaServerAudio::uiPlaybackChanged(int layer, Status s)
|
|
{
|
|
ma_result result;
|
|
|
|
result = m_mae.playbackChanged(layer, s);
|
|
if (result == MA_SUCCESS) {
|
|
m_currentStatus[layer] = s;
|
|
} else {
|
|
qWarning() << "ui playback change error " << result << " status " << statusToString(s) << "layer" << layer;
|
|
}
|
|
}
|
|
|
|
void libreMediaServerAudio::uiLoadMedia(int layer, QString mediaFile)
|
|
{
|
|
ma_result result;
|
|
|
|
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
|
|
return;
|
|
result = m_mae.loadMedia(layer, mediaFile.toLatin1().data());
|
|
if (result == MA_SUCCESS) {
|
|
m_currentMedia[layer] = mediaFile;
|
|
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
|
|
} else {
|
|
qWarning() << "ui load media error" << result << "file" << mediaFile << "layer" << layer;
|
|
}
|
|
}
|
|
#endif
|