/* Libre Media Server Audio - An Open source Media Server for arts and performing. (c) Criptomart - Santiago NoreƱa 2012-2024 https://git.criptomart.net/libremediaserver This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "libremediaserver-audio.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