lms-audio/src/libremediaserver-audio.cpp
2024-06-18 14:59:31 +02:00

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(this);
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