pan y pitchs faders horizontales, funciona varias instancias con
multidispositivo y patcheable en jack.
This commit is contained in:
parent
7631e54d51
commit
103a33820e
12 changed files with 188 additions and 105 deletions
|
@ -13,8 +13,8 @@ v 0.2.0 Antígona (26/05/2024)
|
||||||
+ Pan.
|
+ Pan.
|
||||||
+ Show faders values. New SliderGroup class.
|
+ Show faders values. New SliderGroup class.
|
||||||
+ Entry Point 16 bits.
|
+ Entry Point 16 bits.
|
||||||
+ Refactor AudioMasterWidget to AudioDMXReceptionWidget.
|
+ Refactor AudioMasterWidget to dmxWidget.
|
||||||
+ Read mp3, flac, wav (mp3 has given some errors seeking cursor...).
|
+ Read mp3, flac, wav (mp3 has given some errors seeking cursors...). Audio Engine is working at 48Khz and 32 bits pcm float, if media files are encoding at same configuration, it saves a resampling operation later live.
|
||||||
+ Removed settings dialog, only read xml conf file at startup.
|
+ Removed settings dialog, only read xml conf file at startup.
|
||||||
+ Real dynamic variable number of layers based on conf file setting.
|
+ Real dynamic variable number of layers based on conf file setting.
|
||||||
+ OlaThread send double channels (volume, entry point, load media) only once for each dmx frame buffer.
|
+ OlaThread send double channels (volume, entry point, load media) only once for each dmx frame buffer.
|
||||||
|
@ -23,8 +23,12 @@ v 0.2.0 Antígona (26/05/2024)
|
||||||
+ New Status "Iddle" in playbacks if is not loaded.
|
+ New Status "Iddle" in playbacks if is not loaded.
|
||||||
+ New DMX personality version, better sort for audio needs (first load media, set vol, pan, etc, last playback order);
|
+ New DMX personality version, better sort for audio needs (first load media, set vol, pan, etc, last playback order);
|
||||||
+ Refresh layer values when it loads a new sound file.
|
+ Refresh layer values when it loads a new sound file.
|
||||||
+ No QtSignals for sending data, better performance about 20% in my machine. Now, libremediaserver only updates values in AudioWidget, ui refresh is doing with a timer in audiowidget, so there is not problems between graphical and ola thread (the callback).
|
+ No QtSignals for sending data, better performance about 20% in my machine. Now, libremediaserver only updates values in AudioWidget, ui refresh is doing with a timer in audiowidget, so there is not problems between graphical and ola thread (the callback). Signals are used only from Ui to libreMediaServer to notify user interactions and Qtimers.
|
||||||
+ Load media files from ui clicking in the media labels.
|
+ Load media files from ui clicking in the media labels.
|
||||||
|
+ New Play Modes:
|
||||||
|
- Play all medias found in one folder.
|
||||||
|
- Play all medias in one folder consecutevily.
|
||||||
|
- Play all medias in one folder randomly.
|
||||||
|
|
||||||
v 0.1.3 Leúcade (19/04/2024)
|
v 0.1.3 Leúcade (19/04/2024)
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,6 @@ v 0.2.2
|
||||||
|
|
||||||
v 0.2.1
|
v 0.2.1
|
||||||
- Multi devices output.
|
- Multi devices output.
|
||||||
- Play Mode:
|
|
||||||
- Play all medias found in folder consecutevily or random, with loop.
|
|
||||||
- Play all medias, consecutevily and random, with loop.
|
|
||||||
- mute/panic on layer.
|
- mute/panic on layer.
|
||||||
- Master Bus Layer:
|
- Master Bus Layer:
|
||||||
- each layer will have one "Gain" prefader that acts in source, "Vol" in v 1.3.
|
- each layer will have one "Gain" prefader that acts in source, "Vol" in v 1.3.
|
||||||
|
|
|
@ -46,11 +46,11 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
|
||||||
m_progressTime = new QTimeEdit;
|
m_progressTime = new QTimeEdit;
|
||||||
m_progressTime->setToolTip("Current Time");
|
m_progressTime->setToolTip("Current Time");
|
||||||
m_progressTime->setObjectName("Current Time");
|
m_progressTime->setObjectName("Current Time");
|
||||||
m_progressTime->setDisplayFormat("mm:ss:zz");
|
m_progressTime->setDisplayFormat("mm:ss:zzz");
|
||||||
m_progressTime->setReadOnly(true);
|
m_progressTime->setReadOnly(true);
|
||||||
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
m_progressTime->setMinimumWidth(80);
|
m_progressTime->setMinimumWidth(80);
|
||||||
m_progressTime->setMaximumWidth(80);
|
//m_progressTime->setMaximumWidth(80);
|
||||||
m_progressTime->setFocusPolicy(Qt::NoFocus);
|
m_progressTime->setFocusPolicy(Qt::NoFocus);
|
||||||
m_progressTime->setAlignment(Qt::AlignHCenter);
|
m_progressTime->setAlignment(Qt::AlignHCenter);
|
||||||
m_progressTime->setContentsMargins(0,0,0,0);
|
m_progressTime->setContentsMargins(0,0,0,0);
|
||||||
|
@ -68,22 +68,22 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
|
||||||
status->addWidget(m_progressTime);
|
status->addWidget(m_progressTime);
|
||||||
status->addWidget(m_totalTimeValue);
|
status->addWidget(m_totalTimeValue);
|
||||||
layout->addLayout(status);
|
layout->addLayout(status);
|
||||||
QHBoxLayout *volumeBox = new QHBoxLayout;
|
QVBoxLayout *volumeBox = new QVBoxLayout;
|
||||||
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
|
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
|
||||||
volumeBox->addWidget(m_volume);
|
volumeBox->addWidget(m_pitch);
|
||||||
connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
|
connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
|
||||||
m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL);
|
m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL);
|
||||||
volumeBox->addWidget(m_pan);
|
volumeBox->addWidget(m_pan);
|
||||||
connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int)));
|
connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int)));
|
||||||
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
|
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
|
||||||
volumeBox->addWidget(m_pitch);
|
volumeBox->addWidget(m_volume);
|
||||||
|
connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
|
||||||
volumeBox->setSpacing(0);
|
volumeBox->setSpacing(0);
|
||||||
volumeBox->setContentsMargins(0, 0, 0, 0);
|
volumeBox->setContentsMargins(0, 0, 0, 0);
|
||||||
connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
|
|
||||||
layout->addLayout(volumeBox);
|
layout->addLayout(volumeBox);
|
||||||
layout->setAlignment(Qt::AlignHCenter);
|
layout->setAlignment(Qt::AlignHCenter);
|
||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
layout->setContentsMargins(2, 2, 2, 2);
|
layout->setContentsMargins(1, 1, 1, 1);
|
||||||
this->setLayout(layout);
|
this->setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,13 +113,17 @@ void AudioLayerWidget::toggleSuspendResume()
|
||||||
switch (m_status) {
|
switch (m_status) {
|
||||||
case Status::PlayingLoop:
|
case Status::PlayingLoop:
|
||||||
case Status::PlayingOnce:
|
case Status::PlayingOnce:
|
||||||
|
case Status::PlayingFolder:
|
||||||
|
case Status::PlayingFolderLoop:
|
||||||
|
case Status::PlayingFolderRandom:
|
||||||
|
m_oldStatus = m_status;
|
||||||
this->setPlaybackStatus(Status::Paused);
|
this->setPlaybackStatus(Status::Paused);
|
||||||
emit uiPlaybackChanged(m_layer, Status::Paused);
|
emit uiPlaybackChanged(m_layer, Status::Paused);
|
||||||
break;
|
break;
|
||||||
case Status::Paused:
|
case Status::Paused:
|
||||||
case Status::Stopped:
|
case Status::Stopped:
|
||||||
this->setPlaybackStatus(Status::PlayingLoop);
|
this->setPlaybackStatus(m_oldStatus);
|
||||||
emit uiPlaybackChanged(m_layer, Status::PlayingLoop);
|
emit uiPlaybackChanged(m_layer, m_oldStatus);
|
||||||
case Status::Iddle:
|
case Status::Iddle:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -174,10 +178,9 @@ void AudioLayerWidget::setMediaFile(QString file)
|
||||||
|
|
||||||
void AudioLayerWidget::setPlaybackStatus(Status s)
|
void AudioLayerWidget::setPlaybackStatus(Status s)
|
||||||
{
|
{
|
||||||
Status status = static_cast<Status>(s);
|
|
||||||
m_suspendResumeButton->blockSignals(true);
|
m_suspendResumeButton->blockSignals(true);
|
||||||
m_status = status;
|
m_status = s;
|
||||||
m_suspendResumeButton->setText(StatusStr[status]);
|
m_suspendResumeButton->setText(StatusStr[s]);
|
||||||
m_suspendResumeButton->blockSignals(false);
|
m_suspendResumeButton->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Status m_status;
|
Status m_status;
|
||||||
|
Status m_oldStatus;
|
||||||
int m_layer;
|
int m_layer;
|
||||||
QPushButton *m_suspendResumeButton;
|
QPushButton *m_suspendResumeButton;
|
||||||
ClickableLabel *m_fileValue;
|
ClickableLabel *m_fileValue;
|
||||||
|
|
|
@ -5,7 +5,8 @@ AudioWidget::AudioWidget(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent)
|
||||||
, m_layout(new QHBoxLayout())
|
, m_layout(new QHBoxLayout())
|
||||||
{
|
{
|
||||||
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
|
m_layers = Settings::getInstance()->getLayersNumber();
|
||||||
|
for (uint i= 0; i < m_layers; i++ ) {
|
||||||
AudioLayerWidget *alw = new AudioLayerWidget(this, i);
|
AudioLayerWidget *alw = new AudioLayerWidget(this, i);
|
||||||
m_layout->insertWidget(i, alw);
|
m_layout->insertWidget(i, alw);
|
||||||
connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SIGNAL(uiSliderChanged(int, Slider, int)));
|
connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SIGNAL(uiSliderChanged(int, Slider, int)));
|
||||||
|
@ -64,7 +65,7 @@ void AudioWidget::cursorChanged(int layer, float cursor)
|
||||||
|
|
||||||
void AudioWidget::refreshUi()
|
void AudioWidget::refreshUi()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_LAYERS; i++)
|
for (uint i = 0; i < m_layers; i++)
|
||||||
{
|
{
|
||||||
if (m_layerUpdate[i].updated) {
|
if (m_layerUpdate[i].updated) {
|
||||||
QLayoutItem * const item = m_layout->itemAt(i);
|
QLayoutItem * const item = m_layout->itemAt(i);
|
||||||
|
|
|
@ -18,6 +18,7 @@ private:
|
||||||
QHBoxLayout *m_layout;
|
QHBoxLayout *m_layout;
|
||||||
layerData m_layerUpdate[MAX_LAYERS];
|
layerData m_layerUpdate[MAX_LAYERS];
|
||||||
QTimer *m_refreshUi;
|
QTimer *m_refreshUi;
|
||||||
|
uint m_layers;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void volChanged(int layer, float vol);
|
void volChanged(int layer, float vol);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#define DEFAULT_FILE "lms-audio.xlm"
|
#define DEFAULT_FILE "lms-audio.xlm"
|
||||||
#define MAX_LAYERS 4
|
#define MAX_LAYERS 4
|
||||||
#define MAX_AUDIODEVICES 8
|
#define MAX_AUDIODEVICES 8
|
||||||
#define UI_REFRESH_TIME 66
|
#define UI_REFRESH_TIME 100
|
||||||
#define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks
|
#define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks
|
||||||
|
|
||||||
struct dmxSetting {
|
struct dmxSetting {
|
||||||
|
@ -32,12 +32,12 @@ static const char* StatusStr[] =
|
||||||
{
|
{
|
||||||
"Stop",
|
"Stop",
|
||||||
"Pause",
|
"Pause",
|
||||||
"Playing One",
|
"Play One",
|
||||||
"Playing One Loop",
|
"Play One Loop",
|
||||||
"Iddle",
|
"Iddle",
|
||||||
"Playing Folder",
|
"Play Folder",
|
||||||
"Playing Folder Loop",
|
"Play Folder Loop",
|
||||||
"Playing Folder Random",
|
"Play Folder Rand",
|
||||||
0x0
|
0x0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
||||||
#ifndef NOGUI
|
#ifndef NOGUI
|
||||||
if (m_ui) {
|
if (m_ui) {
|
||||||
m_lmsUi->m_aw->playbackChanged(layer, s);
|
m_lmsUi->m_aw->playbackChanged(layer, s);
|
||||||
//m_lmsUi->m_aw->cursorChanged(layer, m_mae.getCursor(layer));
|
m_played.clear();
|
||||||
|
m_played.append(m_ola->getValue(layer, DMX_FILE));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -153,8 +154,6 @@ void libreMediaServerAudio::refreshUi() {
|
||||||
m_updateUi[i][3] = -1;
|
m_updateUi[i][3] = -1;
|
||||||
}
|
}
|
||||||
if (m_mae.getAtEnd(i)) {
|
if (m_mae.getAtEnd(i)) {
|
||||||
if (m_played.isEmpty())
|
|
||||||
m_played.append(m_ola->getValue(i, DMX_FILE));
|
|
||||||
if (m_currentStatus[i] == Status::PlayingOnce) {
|
if (m_currentStatus[i] == Status::PlayingOnce) {
|
||||||
m_currentStatus[i] = Status::Stopped;
|
m_currentStatus[i] = Status::Stopped;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ ma_result MiniAudioEngine::startContext()
|
||||||
resourceManagerConfig = ma_resource_manager_config_init();
|
resourceManagerConfig = ma_resource_manager_config_init();
|
||||||
resourceManagerConfig.decodedFormat = ma_format_f32; /* ma_format_f32 should almost always be used as that's what the engine (and most everything else) uses for mixing. */
|
resourceManagerConfig.decodedFormat = ma_format_f32; /* ma_format_f32 should almost always be used as that's what the engine (and most everything else) uses for mixing. */
|
||||||
resourceManagerConfig.decodedChannels = 0;
|
resourceManagerConfig.decodedChannels = 0;
|
||||||
resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_48000;
|
resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_44100;
|
||||||
resourceManagerConfig.jobThreadCount = 4;
|
resourceManagerConfig.jobThreadCount = 4;
|
||||||
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
|
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
|
@ -129,6 +129,7 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
result = ma_sound_init_from_file(&engine, file, \
|
result = ma_sound_init_from_file(&engine, file, \
|
||||||
MA_SOUND_FLAG_NO_SPATIALIZATION \
|
MA_SOUND_FLAG_NO_SPATIALIZATION \
|
||||||
| MA_SOUND_FLAG_DECODE \
|
| MA_SOUND_FLAG_DECODE \
|
||||||
|
| MA_SOUND_FLAG_STREAM \
|
||||||
/*| MA_SOUND_FLAG_NO_PITCH \*/
|
/*| MA_SOUND_FLAG_NO_PITCH \*/
|
||||||
, NULL, NULL, &m_currentSound[layer]);
|
, NULL, NULL, &m_currentSound[layer]);
|
||||||
if (result != MA_SUCCESS)
|
if (result != MA_SUCCESS)
|
||||||
|
@ -144,22 +145,15 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
float MiniAudioEngine::getDuration(int layer)
|
float MiniAudioEngine::getDuration(int layer)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
ma_uint64 lengthInPCMFrames;
|
|
||||||
ma_uint32 sampleRate;
|
|
||||||
float ret;
|
float ret;
|
||||||
|
|
||||||
if (m_mediaLoaded[layer] == false)
|
if (m_mediaLoaded[layer] == false)
|
||||||
return MA_DOES_NOT_EXIST;
|
return MA_DOES_NOT_EXIST;
|
||||||
result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &lengthInPCMFrames);
|
result = ma_sound_get_length_in_seconds(&m_currentSound[layer], &ret);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = ma_sound_get_data_format(&m_currentSound[layer], NULL, NULL, &sampleRate, NULL, 0);
|
return (ret * 1000);
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return MA_ERROR;
|
|
||||||
}
|
|
||||||
ret = 1000.0f * (lengthInPCMFrames / float(sampleRate));
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float MiniAudioEngine::getCursor(int layer)
|
float MiniAudioEngine::getCursor(int layer)
|
||||||
|
@ -233,27 +227,25 @@ ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
|
||||||
|
|
||||||
if (m_mediaLoaded[layer] == false)
|
if (m_mediaLoaded[layer] == false)
|
||||||
return MA_DOES_NOT_EXIST;
|
return MA_DOES_NOT_EXIST;
|
||||||
|
bool loop = false;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Status::Paused:
|
case Status::Paused:
|
||||||
result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
|
result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
|
||||||
break;
|
break;
|
||||||
case Status::Stopped:
|
case Status::Stopped:
|
||||||
result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
|
ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
|
||||||
result = this->seekToCursor(layer, m_currentLayerValues[layer].cursor);
|
result = this->seekToCursor(layer, m_currentLayerValues[layer].cursor);
|
||||||
break;
|
break;
|
||||||
case Status::PlayingLoop:
|
case Status::PlayingLoop:
|
||||||
ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
|
loop = true;
|
||||||
ma_sound_set_looping(&m_currentSound[layer], true);
|
|
||||||
result = ma_sound_start(&m_currentSound[layer]);
|
|
||||||
break;
|
|
||||||
case Status::PlayingOnce:
|
case Status::PlayingOnce:
|
||||||
case Status::PlayingFolder:
|
case Status::PlayingFolder:
|
||||||
case Status::PlayingFolderLoop:
|
case Status::PlayingFolderLoop:
|
||||||
case Status::PlayingFolderRandom:
|
case Status::PlayingFolderRandom:
|
||||||
ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
|
ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
|
||||||
ma_sound_set_looping(&m_currentSound[layer], false);
|
ma_sound_set_looping(&m_currentSound[layer], loop);
|
||||||
result = ma_sound_start(&m_currentSound[layer]);
|
result = ma_sound_start(&m_currentSound[layer]);
|
||||||
break;
|
//this->volChanged(layer, m_currentLayerValues[layer].vol); // glitch when seek to cursor, how flush the audio buffer?
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -273,8 +265,7 @@ ma_result MiniAudioEngine::seekToCursor(int layer, int cursor)
|
||||||
if (result != MA_SUCCESS) { return result; }
|
if (result != MA_SUCCESS) { return result; }
|
||||||
start = (cursor * end) / 65025;
|
start = (cursor * end) / 65025;
|
||||||
result = ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start);
|
result = ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start);
|
||||||
//if (result != MA_SUCCESS) { return result; }
|
//result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end); // this do nothing here, it must be done after set_looping or start?
|
||||||
//result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end);
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#ifndef MINIAUDIOENGINE_H
|
#ifndef MINIAUDIOENGINE_H
|
||||||
#define MINIAUDIOENGINE_H
|
#define MINIAUDIOENGINE_H
|
||||||
|
|
||||||
|
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS 1
|
||||||
|
#define MA_ENABLE_JACK 1
|
||||||
|
#define MA_NO_GENERATION 1
|
||||||
|
#define MA_DEBUG_OUTPUT 1
|
||||||
|
#define MA_DISABLE_PULSEAUDIO
|
||||||
#define MINIAUDIO_IMPLEMENTATION
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
#include "miniaudio.h"
|
#include "miniaudio.h"
|
||||||
#include "defines.h" // MAX_LAYERS
|
#include "defines.h" // MAX_LAYERS
|
||||||
#include <QDebug> // prints messages
|
#include <QDebug> // prints messages
|
||||||
#define MA_DEBUG_OUTPUT
|
|
||||||
|
|
||||||
class MiniAudioEngine
|
class MiniAudioEngine
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
#include "slidergroup.h"
|
#include "slidergroup.h"
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
#include <QStyle>
|
||||||
|
|
||||||
|
DoubleSpinBoxClickable::DoubleSpinBoxClickable(QWidget *parent)
|
||||||
|
: QDoubleSpinBox{parent} {}
|
||||||
|
|
||||||
|
DoubleSpinBoxClickable::~DoubleSpinBoxClickable() {}
|
||||||
|
|
||||||
|
SliderClickDisable::SliderClickDisable(QWidget *parent)
|
||||||
|
: QSlider{parent} {}
|
||||||
|
|
||||||
|
SliderClickDisable::~SliderClickDisable() {}
|
||||||
|
|
||||||
SliderGroup::SliderGroup(QString name,
|
SliderGroup::SliderGroup(QString name,
|
||||||
int min,
|
int min,
|
||||||
int max,
|
int max,
|
||||||
|
@ -7,42 +19,46 @@ SliderGroup::SliderGroup(QString name,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QBoxLayout *layout;
|
||||||
|
if (decimals) {
|
||||||
|
layout = new QVBoxLayout;
|
||||||
|
slider.setOrientation(Qt::Vertical);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
layout = new QHBoxLayout;
|
||||||
|
slider.setOrientation(Qt::Horizontal);
|
||||||
|
slider.setMinimumHeight(10);
|
||||||
|
}
|
||||||
layout->setAlignment(Qt::AlignHCenter);
|
layout->setAlignment(Qt::AlignHCenter);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
//this->setMaximumWidth(40);
|
slider.setFocusPolicy(Qt::StrongFocus);
|
||||||
slider = new QSlider(Qt::Orientation::Vertical);
|
slider.setTickPosition(QSlider::TicksBothSides);
|
||||||
slider->setFocusPolicy(Qt::StrongFocus);
|
slider.setTickInterval((max - min) / 11);
|
||||||
slider->setTickPosition(QSlider::TicksBothSides);
|
slider.setMinimumHeight(0);
|
||||||
slider->setTickInterval((max - min) / 11);
|
slider.setSingleStep(1);
|
||||||
slider->setMinimumHeight(0);
|
slider.setRange(min, max);
|
||||||
slider->setSingleStep(1);
|
slider.setValue(0);
|
||||||
slider->setRange(min, max);
|
slider.setMinimumWidth(50);
|
||||||
slider->setValue(0);
|
slider.setToolTip(name);
|
||||||
slider->setMinimumWidth(50);
|
slider.setStyleSheet("QSlider {"
|
||||||
slider->setToolTip(name);
|
|
||||||
slider->setStyleSheet("QSlider {"
|
|
||||||
"border: 1px solid #5a4855;"
|
"border: 1px solid #5a4855;"
|
||||||
"margin: 0px;"
|
"margin: 0px;}"
|
||||||
"height: 200px;"
|
|
||||||
"width: 50px;}"
|
|
||||||
);
|
);
|
||||||
slider->setContentsMargins(0, 0, 0, 0);
|
slider.setContentsMargins(0, 0, 0, 0);
|
||||||
valueBox = new QDoubleSpinBox();
|
valueBox.setFocusPolicy(Qt::NoFocus);
|
||||||
valueBox->setFocusPolicy(Qt::NoFocus);
|
valueBox.setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
valueBox.setMinimumWidth(50);
|
||||||
valueBox->setMinimumWidth(50);
|
valueBox.setRange(min, max);
|
||||||
valueBox->setRange(min, max);
|
valueBox.setValue(0);
|
||||||
valueBox->setValue(0);
|
valueBox.setDecimals(decimals);
|
||||||
valueBox->setDecimals(decimals);
|
valueBox.setObjectName(name);
|
||||||
valueBox->setObjectName(name);
|
valueBox.setToolTip(name);
|
||||||
valueBox->setToolTip(name);
|
valueBox.setAlignment(Qt::AlignHCenter);
|
||||||
valueBox->setAlignment(Qt::AlignHCenter);
|
valueBox.setContentsMargins(0, 0, 0, 0);
|
||||||
valueBox->setContentsMargins(0, 0, 0, 0);
|
connect(&slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
|
||||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
|
connect(&valueBox, SIGNAL(enableSlider()), this, SLOT(enableSlider()));
|
||||||
//connect(slider, SIGNAL(mousePressEvent(QMouseEvent)), this, SLOT(mousePressEvent(QMouseEvent *)));
|
layout->addWidget(&slider);
|
||||||
layout->addWidget(slider);
|
layout->addWidget(&valueBox);
|
||||||
layout->addWidget(valueBox);
|
|
||||||
this->setStyleSheet("border: 1px solid #5a4855;"
|
this->setStyleSheet("border: 1px solid #5a4855;"
|
||||||
"width: 50px;"
|
"width: 50px;"
|
||||||
"margin: 0px;"
|
"margin: 0px;"
|
||||||
|
@ -55,27 +71,19 @@ SliderGroup::SliderGroup(QString name,
|
||||||
|
|
||||||
void SliderGroup::sliderValueChanged(int value)
|
void SliderGroup::sliderValueChanged(int value)
|
||||||
{
|
{
|
||||||
valueBox->blockSignals(true);
|
valueBox.blockSignals(true);
|
||||||
valueBox->setValue(value);
|
valueBox.setValue(value);
|
||||||
valueBox->blockSignals(false);
|
valueBox.blockSignals(false);
|
||||||
emit valueChanged(value);
|
emit valueChanged(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
void SliderGroup::setValue(float value)
|
void SliderGroup::setValue(float value)
|
||||||
{
|
{
|
||||||
slider->blockSignals(true);
|
slider.blockSignals(true);
|
||||||
valueBox->blockSignals(true);
|
valueBox.blockSignals(true);
|
||||||
if (int(value) != slider->value())
|
if (int(value) != slider.value())
|
||||||
slider->setValue(value);
|
slider.setValue(value);
|
||||||
valueBox->setValue(value);
|
valueBox.setValue(value);
|
||||||
slider->blockSignals(false);
|
slider.blockSignals(false);
|
||||||
valueBox->blockSignals(false);
|
valueBox.blockSignals(false);
|
||||||
}
|
|
||||||
|
|
||||||
void SliderGroup::mousePressEvent(QMouseEvent* event) {
|
|
||||||
Q_UNUSED(event);
|
|
||||||
if (slider->isEnabled())
|
|
||||||
slider->setDisabled(true);
|
|
||||||
else
|
|
||||||
slider->setDisabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,78 @@
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
/*
|
||||||
|
//slider->installEventFilter(new QSliderAnalyser);
|
||||||
|
class QSliderAnalyser
|
||||||
|
: public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QSliderAnalyser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~QSliderAnalyser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject* object, QEvent* event) override
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
qDebug() << event->type() << object->objectName();
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
|
||||||
|
class DoubleSpinBoxClickable: public QDoubleSpinBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
DoubleSpinBoxClickable(QWidget *parent = 0);
|
||||||
|
~DoubleSpinBoxClickable();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void enableSlider();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent ( QMouseEvent * event )
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
qDebug() << "enabling slider";
|
||||||
|
emit(enableSlider());
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SliderClickDisable
|
||||||
|
: public QSlider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SliderClickDisable(QWidget *parent = Q_NULLPTR);
|
||||||
|
~SliderClickDisable();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent ( QMouseEvent * event )
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::RightButton)
|
||||||
|
{
|
||||||
|
if (this->isEnabled()) {
|
||||||
|
qDebug() << "disabling slider";
|
||||||
|
this->setDisabled(true);
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
QSlider::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class SliderGroup : public QWidget
|
class SliderGroup : public QWidget
|
||||||
{
|
{
|
||||||
|
@ -25,10 +97,12 @@ public slots:
|
||||||
void sliderValueChanged(int value);
|
void sliderValueChanged(int value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSlider *slider;
|
SliderClickDisable slider;
|
||||||
QDoubleSpinBox *valueBox;
|
DoubleSpinBoxClickable valueBox;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void enableSlider() { slider.setEnabled(true); }
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent* event);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue