diff --git a/docs/changelog.txt b/docs/changelog.txt index a795e69..6044175 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -13,6 +13,11 @@ v 0.1.3 (1/05/2024) - Ubuntu 22.04 jammy - Use SFML as audio engine - Qt 5.15.3 +- pan +- pitch +- loop +- loop points +- play offset v 0.1.2 (12/08/2015) diff --git a/docs/compiling.txt b/docs/compiling.txt index c9d01c7..54c6e19 100644 --- a/docs/compiling.txt +++ b/docs/compiling.txt @@ -1,7 +1,7 @@ ******************************************************************************* Libre Media Server Audio - An Open source Media Server. (c) Santiago Noreña 2014-2024 -http://git.criptomart.net/libremediaserver +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. @@ -11,7 +11,9 @@ You should have received a copy of the GNU General Public License along with thi 0. Requisites - sudo apt-get install build-essential qmake-qt5 gcc g++ libtool libsfml-dev qtbase5-dev libqt5webkit5-dev qtwebengine5-dev - OLA https://www.openlighting.org/ola/linuxinstall/#Git - -- ToDo: la instalación de OLA es un infierno, hay que empaquetarlo + -- ToDo: la instalación de OLA es un infierno, hay que empaquetarlo o mirar si hay alguna lib de sACN + +https://github.com/ETCLabs/sACN 1. Compiles $ qmake -spec linux-g++ -o Makefile libremediaserver-audio.pro diff --git a/src/audiolayerwidget.cpp b/src/audiolayerwidget.cpp index 79eba4c..d24da6c 100644 --- a/src/audiolayerwidget.cpp +++ b/src/audiolayerwidget.cpp @@ -28,13 +28,19 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name): // status->addWidget(m_receiveDMX); status->addWidget(m_statusLabel); status->addWidget(m_statusValue); + m_loopCheckLabel = new QLabel; + m_loopCheckLabel->setText("Loop"); + m_loopCheck = new QCheckBox(); + connect(m_loopCheck, SIGNAL(stateChanged(int)), this, SLOT(loopChanged(int))); + status->addWidget(m_loopCheckLabel); + status->addWidget(m_loopCheck); layout->addLayout(status); QHBoxLayout *folderLoaded = new QHBoxLayout; m_folderLabel = new QLabel; m_folderLabel->setText(FOLDER_LABEL); m_folderValue = new QLabel; - m_folderValue->setMaximumWidth(150); + m_folderValue->setMaximumWidth(200); folderLoaded->addWidget(m_folderLabel); folderLoaded->addWidget(m_folderValue); layout->addLayout(folderLoaded); @@ -43,24 +49,42 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name): m_fileLabel = new QLabel; m_fileLabel->setText(FILE_LABEL); m_fileValue = new QLabel; - m_fileValue->setMaximumWidth(150); + m_fileValue->setMaximumWidth(200); fileLoaded->addWidget(m_fileLabel); fileLoaded->addWidget(m_fileValue); layout->addLayout(fileLoaded); - QHBoxLayout *volumeBox = new QHBoxLayout; + QGridLayout *volumeBox = new QGridLayout; m_volumeLabel = new QLabel; m_volumeLabel->setText(tr(VOLUME_LABEL)); m_volumeSlider = new QSlider(Qt::Horizontal); m_volumeSlider->setMinimum(0); - m_volumeSlider->setMaximum(80); + m_volumeSlider->setMaximum(90); m_volumeSlider->setSingleStep(1); connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); - volumeBox->addWidget(m_volumeLabel); - volumeBox->addWidget(m_volumeSlider); + volumeBox->addWidget(m_volumeLabel, 0, 0); + volumeBox->addWidget(m_volumeSlider, 0, 1); + m_panLabel = new QLabel; + m_panLabel->setText("Pan"); + m_panSlider = new QSlider(Qt::Horizontal); + m_panSlider->setMinimum(0); + m_panSlider->setMaximum(255); + m_panSlider->setSingleStep(1); + connect(m_panSlider, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int))); + volumeBox->addWidget(m_panLabel, 1, 0); + volumeBox->addWidget(m_panSlider, 1, 1); + m_pitchLabel = new QLabel; + m_pitchLabel->setText("Pitch"); + m_pitchSlider = new QSlider(Qt::Horizontal); + m_pitchSlider->setMinimum(0); + m_pitchSlider->setMaximum(255); + m_pitchSlider->setSingleStep(1); + connect(m_pitchSlider, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int))); + volumeBox->addWidget(m_pitchLabel, 2, 0); + volumeBox->addWidget(m_pitchSlider, 2, 1); layout->addLayout(volumeBox); - QGridLayout *progressTime = new QGridLayout; + QHBoxLayout *progressTime = new QHBoxLayout; m_progressTimeLabel = new QLabel; m_progressTimeLabel->setText(PROGRESS_TIME_LABEL); m_progressTime = new QTimeEdit; @@ -68,19 +92,18 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name): m_progressTime->setDisplayFormat("h:mm:ss:zzz"); m_progressTime->setReadOnly(true); m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons); - m_progressTime->setMaximumWidth(80); - progressTime->addWidget(m_progressTimeLabel, 0 ,0); - progressTime->addWidget(m_progressTime,0 ,1); - + m_progressTime->setMaximumWidth(120); + progressTime->addWidget(m_progressTimeLabel); + progressTime->addWidget(m_progressTime); m_totalTimeLabel = new QLabel; m_totalTimeLabel->setText(TOTAL_TIME_LABEL); m_totalTimeValue = new QTimeEdit; m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz"); m_totalTimeValue->setReadOnly(true); m_totalTimeValue->setButtonSymbols(QAbstractSpinBox::NoButtons); - m_totalTimeValue->setMaximumWidth(80); - progressTime->addWidget(m_totalTimeLabel,1 , 0); - progressTime->addWidget(m_totalTimeValue, 1 ,1); + m_totalTimeValue->setMaximumWidth(120); + progressTime->addWidget(m_totalTimeLabel); + progressTime->addWidget(m_totalTimeValue); layout->addLayout(progressTime); QHBoxLayout *progressSlider = new QHBoxLayout; @@ -100,7 +123,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name): connect(m_watchDMX, SIGNAL(timeout()), this, SLOT(watchDMXExpired())); - m_watchDMX->start(243); + m_watchDMX->start(100); m_music.setAttenuation(0); } @@ -115,6 +138,21 @@ void AudioLayerWidget::volumeChanged(int value) m_music.setVolume(value); } +void AudioLayerWidget::panChanged(int value) +{ + m_music.setPosition((value - 128) / 32.0, 0, 0); +} + +void AudioLayerWidget::pitchChanged(int value) +{ + m_music.setPitch(qreal(value / 128.0 )); +} + +void AudioLayerWidget::loopChanged(int value) +{ + m_music.setLoop(value); +} + void AudioLayerWidget::setVol(qreal vol) { m_music.setVolume(vol); @@ -123,6 +161,22 @@ void AudioLayerWidget::setVol(qreal vol) m_volumeSlider->blockSignals(false); } +void AudioLayerWidget::setPan(qreal pan) +{ + m_music.setPosition(float((pan - 128) / 32.0), 0, 0); + m_panSlider->blockSignals(true); + m_panSlider->setValue(pan); + m_panSlider->blockSignals(false); +} + +void AudioLayerWidget::setPitch(qreal pitch) +{ + m_music.setPitch(float(pitch / 128 )); + m_pitchSlider->blockSignals(true); + m_pitchSlider->setValue(pitch); + m_pitchSlider->blockSignals(false); +} + void AudioLayerWidget::loadMedia(QString file) { if (m_currentMedia.compare(file) == 0 ) { @@ -165,9 +219,13 @@ void AudioLayerWidget::durationChanged(qint64 dur) m_totalTimeValue->setTime(QTime::fromMSecsSinceStartOfDay(dur)); } -void AudioLayerWidget::play() +void AudioLayerWidget::play(bool loop) { m_music.play(); + m_music.setLoop(loop); + m_loopCheck->blockSignals(true); + m_loopCheck->setChecked(m_music.getLoop()); + m_loopCheck->blockSignals(false); } void AudioLayerWidget::pause() @@ -202,6 +260,9 @@ void AudioLayerWidget::watchDMXExpired() { m_progressSlider->setValue(0); break; } + //m_loopCheck->blockSignals(true); + //m_loopCheck->setChecked(m_music.getLoop()); + //m_loopCheck->blockSignals(false); } void AudioLayerWidget::toggleSuspendResume() diff --git a/src/audiolayerwidget.h b/src/audiolayerwidget.h index d026263..e22500c 100644 --- a/src/audiolayerwidget.h +++ b/src/audiolayerwidget.h @@ -35,7 +35,7 @@ public: /** * @brief play */ - void play(); + void play(bool loop); /** * @brief stop @@ -58,6 +58,16 @@ public: */ void resume(); + void setPan(qreal pan); + + void setPitch(qreal pitch); + + void setLoop(bool on); + + //void setEntryPoint(qreal entry); + + //void setEndPoint(qreal end); + public slots: /** @@ -66,10 +76,13 @@ public slots: void toggleSuspendResume(); /** - * @brief Conencted with the slider + * @brief Connected with the slider * @param volume 0 -100 range */ void volumeChanged(int vol); + void panChanged(int vol); + void pitchChanged(int vol); + void loopChanged(int vol); private: @@ -81,6 +94,15 @@ private: QLabel *m_volumeLabel; QSlider *m_volumeSlider; + QLabel *m_panLabel; + QSlider *m_panSlider; + + QLabel *m_pitchLabel; + QSlider *m_pitchSlider; + + QLabel *m_loopCheckLabel; + QCheckBox *m_loopCheck; + QLabel * m_progressLabel; QSlider *m_progressSlider; @@ -96,7 +118,7 @@ private: QLabel * m_folderLabel; QLabel * m_folderValue; - QCheckBox *m_receiveDMX; + //QCheckBox *m_receiveDMX; QTimer *m_watchDMX; QString m_currentMedia; @@ -125,6 +147,4 @@ private slots: void watchDMXExpired(); }; - - #endif // AUDIOLAYERWIDGET_H diff --git a/src/audiomasterwidget.cpp b/src/audiomasterwidget.cpp index 96c195a..4d0f1bb 100644 --- a/src/audiomasterwidget.cpp +++ b/src/audiomasterwidget.cpp @@ -4,25 +4,24 @@ AudioMasterWidget::AudioMasterWidget(QWidget *parent) : QGroupBox(parent) - , m_file(new QLabel) - , m_folder(new QLabel) - , m_vol(new QSlider) - , m_mute(new QCheckBox) - , m_status(new QLabel) + //, m_file(new QLabel) + //, m_folder(new QLabel) + //, m_vol(new QSlider) + //, m_mute(new QCheckBox) + //, m_status(new QLabel) , m_receiveDMX(new QCheckBox) , m_watchDMX(new QTimer) { QVBoxLayout *vbox = new QVBoxLayout; -// vbox->addWidget(status); -// vbox->addWidget(vol); -// vbox->addWidget(mute); + //vbox->addWidget(m_status); + //vbox->addWidget(m_vol); + //vbox->addWidget(m_mute); m_receiveDMX->setText("Receiving DMX"); vbox->addWidget(m_receiveDMX); this->setLayout(vbox); connect(m_watchDMX, SIGNAL(timeout()), this, SLOT(watchDMXExpired())); m_watchDMX->start(1000); - } AudioMasterWidget::~AudioMasterWidget() diff --git a/src/audiomasterwidget.h b/src/audiomasterwidget.h index 5442919..4df388c 100644 --- a/src/audiomasterwidget.h +++ b/src/audiomasterwidget.h @@ -28,11 +28,11 @@ public slots: void updateWatchDMX(); private: - QLabel *m_file; - QLabel *m_folder; - QSlider *m_vol; - QCheckBox *m_mute; - QLabel *m_status; + //QLabel *m_file; + //QLabel *m_folder; + //QSlider *m_vol; + //QCheckBox *m_mute; + //QLabel *m_status; QCheckBox *m_receiveDMX; QTimer *m_watchDMX; diff --git a/src/audiowidget.cpp b/src/audiowidget.cpp index 87a8a4d..1d7ddc8 100644 --- a/src/audiowidget.cpp +++ b/src/audiowidget.cpp @@ -37,12 +37,22 @@ void AudioWidget::volChanged(int layer, qreal vol) { } +void AudioWidget::panChanged(int layer, qreal vol) { + QLayoutItem * const item = layout->itemAt(layer); + dynamic_cast(item->widget())->setPan(vol); +} + +void AudioWidget::pitchChanged(int layer, qreal vol) { + QLayoutItem * const item = layout->itemAt(layer); + dynamic_cast(item->widget())->setPitch(vol); +} + void AudioWidget::playbackChanged(int layer, Status status) { QLayoutItem * const item = layout->itemAt(layer); switch (status) { - case Playing: - dynamic_cast(item->widget())->play(); + case PlayingOnce: + dynamic_cast(item->widget())->play(false); break; case Stopped: dynamic_cast(item->widget())->stop(); @@ -50,6 +60,9 @@ void AudioWidget::playbackChanged(int layer, Status status) case Paused: dynamic_cast(item->widget())->pause(); break; + case PlayingLoop: + dynamic_cast(item->widget())->play(true); + break; } } /* diff --git a/src/audiowidget.h b/src/audiowidget.h index 30d67b6..2243a34 100644 --- a/src/audiowidget.h +++ b/src/audiowidget.h @@ -24,6 +24,8 @@ protected: static AudioWidget *getInstance(); void mediaLoaded(int layer, QString media ); void volChanged(int layer, qreal vol); + void panChanged(int layer, qreal pan); + void pitchChanged(int layer, qreal pitch); void playbackChanged(int layer, Status status); private: diff --git a/src/defines.h b/src/defines.h index 9f6316a..961ec69 100644 --- a/src/defines.h +++ b/src/defines.h @@ -5,7 +5,7 @@ #define COPYRIGHT "(C) 2014-2024 Santi Norena lms@criptomart.net" #define LICENSE "GPL 3 License. See LICENSE.txt and credits.txt for details" -#define LAYERS_NUMBER 3 +#define LAYERS_NUMBER 4 // esto tiene que desaparecer #define DEFAULT_FILE "lms-audio.xlm" @@ -29,7 +29,7 @@ const int BufferSize = 262144; #define TOTAL_TIME_LABEL "Total" #define FILE_LABEL "File:" #define FOLDER_LABEL "Folder:" -#define STATUS_LABEL " Status: " +#define STATUS_LABEL "Status: " #define NOTIFY_INTERVAL 150 #define PULL_TIMER_INTERVAL 10 @@ -59,9 +59,10 @@ struct MediaFolder { enum Status { - Stopped, ///< Sound is not playing - Paused, ///< Sound is paused - Playing ///< Sound is playing + Stopped, + Paused, + PlayingOnce, + PlayingLoop, }; #endif // DEFINES_H diff --git a/src/dmxPersonality.h b/src/dmxPersonality.h index 1728938..f17231e 100644 --- a/src/dmxPersonality.h +++ b/src/dmxPersonality.h @@ -9,13 +9,16 @@ 3 - Folder 4 - File 5 - Playback - 0-24 : Play. Reproduce desde el inicio del fichero. - 25-49: Stop. - 50-74: Resume. Reproduce desde el punto desde el que se paró, o desde el punto designado por Entry Point. + 0-24 : Play once. + 25-49: Stop. Returns to start of file. + 50-74: Pause. It keeps the time of reproductions. + 75-99: Play loop. 6 - Control - Reservado, sin uso en este momento. 7 - Volume Fine 8 - Entry Point Coarse - Punto de entrada de reproducción. 9 - Entry Point Fine - El valor de estos dos canales en centésimas de segundo. +10 - Pan +11 - Pitch */ // ToDo: Tiene bastante sentido cambiar estos defines por un enum @@ -30,7 +33,8 @@ #define VOLUME_FINE 6 #define ENTRY_POINT_COARSE 7 #define ENTRY_POINT_FINE 8 +#define PITCH 9 -#define LAYER_CHANNELS 4 // ToDo: esto tiene que desaparecer +#define LAYER_CHANNELS 10 #endif // DMXPERSONALITY_H diff --git a/src/layersettingswidget.ui b/src/layersettingswidget.ui index 6809a48..a5d5695 100644 --- a/src/layersettingswidget.ui +++ b/src/layersettingswidget.ui @@ -22,6 +22,9 @@ 31 + + 64 + @@ -35,6 +38,35 @@ Address + + 497 + + + + + + 20 + 0 + 67 + 17 + + + + Universe + + + + + + 110 + 0 + 67 + 17 + + + + Address + diff --git a/src/libremediaserver-audio.cpp b/src/libremediaserver-audio.cpp index 8970ff4..d34abe9 100644 --- a/src/libremediaserver-audio.cpp +++ b/src/libremediaserver-audio.cpp @@ -1,7 +1,7 @@ /* Libre Media Server - A Media Server Sotfware for stage and performing - Copyright (C) 2012-2014 Santi Noreña libremediaserver@gmail.com + Copyright (C) 2012-2024 Santi Noreña lms@criptomart.net 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 @@ -181,7 +181,10 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) AudioWidget::getInstance()->volChanged(layer, f / 655.35); break; case PAN: - f = (float)value / 255; + AudioWidget::getInstance()->panChanged(layer, value); + break; + case PITCH: + AudioWidget::getInstance()->pitchChanged(layer, value); break; case PLAYBACK: if (value == 0) @@ -189,7 +192,7 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) aux = value / 25; switch (aux) { case 0 : - AudioWidget::getInstance()->playbackChanged(layer, Playing); + AudioWidget::getInstance()->playbackChanged(layer, PlayingOnce); break; case 1 : AudioWidget::getInstance()->playbackChanged(layer, Stopped); @@ -197,6 +200,9 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) case 2 : AudioWidget::getInstance()->playbackChanged(layer, Paused); break; + case 3 : + AudioWidget::getInstance()->playbackChanged(layer, PlayingLoop); + break; } default: break;