Most colors are now configurable and added drum pad settings dialog

This commit is contained in:
2023-01-01 07:13:48 +01:00
parent d4ca6bdd12
commit 8483cbba7d
32 changed files with 1299 additions and 167 deletions

View File

@@ -5,7 +5,8 @@
DrumPadPresetDetailWidget::DrumPadPresetDetailWidget(QWidget *parent) :
QScrollArea{parent},
m_ui{std::make_unique<Ui::DrumPadPresetDetailWidget>()}
m_ui{std::make_unique<Ui::DrumPadPresetDetailWidget>()},
m_tagsModel{this}
{
m_ui->setupUi(this);

View File

@@ -8,6 +8,8 @@
#include "audioformat.h"
#include "midicontainers.h"
#include "drummachinesettings.h"
#include "drumpadsettingsdialog.h"
DrumPadSamplesWidget::DrumPadSamplesWidget(QWidget *parent) :
QWidget{parent},
@@ -15,8 +17,8 @@ DrumPadSamplesWidget::DrumPadSamplesWidget(QWidget *parent) :
{
m_ui->setupUi(this);
connect(m_ui->checkBox, &QCheckBox::toggled, this, &DrumPadSamplesWidget::updateWidgets);
connect(m_ui->pushButtonSettings, &QAbstractButton::pressed, this, &DrumPadSamplesWidget::showSettings);
connect(m_ui->pushButtonSwap, &QAbstractButton::toggled, this, &DrumPadSamplesWidget::updateWidgets);
connect(m_ui->pushButtonStopAll, &QAbstractButton::pressed, this, &DrumPadSamplesWidget::stopAll);
quint8 padNr{};
@@ -32,6 +34,14 @@ DrumPadSamplesWidget::~DrumPadSamplesWidget() = default;
void DrumPadSamplesWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
m_ui->pushButtonSwap->setLearnSetting(settings.drumpadSwap());
m_ui->pushButtonStopAll->setLearnSetting(settings.drumpadStopAll());
connect(m_ui->pushButtonSwap, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadSwap);
connect(m_ui->pushButtonStopAll, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadStopAll);
for (DrumPadSampleWidget &widget : getWidgets())
widget.loadSettings(settings);
}
@@ -45,11 +55,8 @@ void DrumPadSamplesWidget::setPreset(const drumpad_presets::Preset &preset)
void DrumPadSamplesWidget::midiReceived(const midi::MidiMessage &message)
{
if (message == midi::MidiMessage{.channel=0,.cmd=midi::Command::ControlChange,.flag=true,.note=64,.velocity=127})
{
m_ui->checkBox->toggle();
return;
}
m_ui->pushButtonSwap->midiReceived(message);
m_ui->pushButtonStopAll->midiReceived(message);
for (DrumPadSampleWidget &widget : getWidgets())
widget.midiReceived(message);
@@ -75,14 +82,46 @@ void DrumPadSamplesWidget::injectDecodingThread(QThread &thread)
void DrumPadSamplesWidget::unsendColors()
{
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonSwap->learnSetting().channel,
.cmd = m_ui->pushButtonSwap->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonSwap->learnSetting().note,
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStopAll->learnSetting().channel,
.cmd = m_ui->pushButtonStopAll->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStopAll->learnSetting().note,
.velocity = color
});
for (DrumPadSampleWidget &widget : getWidgets())
widget.unsendColor();
}
void DrumPadSamplesWidget::sendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonSwap->learnSetting().channel,
.cmd = m_ui->pushButtonSwap->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonSwap->learnSetting().note,
.velocity = m_settings ? m_settings->drumpadColorSwap() : quint8{127}
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStopAll->learnSetting().channel,
.cmd = m_ui->pushButtonStopAll->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStopAll->learnSetting().note,
.velocity = m_settings ? m_settings->drumpadColorStopAll() : quint8{127}
});
for (DrumPadSampleWidget &widget : getWidgets())
widget.sendColor();
widget.sendColor(true);
}
void DrumPadSamplesWidget::sequencerTriggerSample(int index)
@@ -96,6 +135,18 @@ void DrumPadSamplesWidget::sequencerTriggerSample(int index)
widgets[index].get().pressed();
}
void DrumPadSamplesWidget::showSettings()
{
if (!m_settings)
{
qWarning() << "settings are missing";
return;
}
DrumPadSettingsDialog dialog{*m_settings, this};
dialog.exec();
}
void DrumPadSamplesWidget::chokeTriggered(int choke)
{
for (DrumPadSampleWidget &widget : getWidgets())
@@ -114,7 +165,7 @@ void DrumPadSamplesWidget::updateWidgets()
auto files = *m_preset.files;
if (m_ui->checkBox->isChecked())
if (m_ui->pushButtonSwap->isChecked())
for (int i = 0; i < 12; i++)
std::swap(files[i], files[i+12]);

View File

@@ -44,6 +44,7 @@ public slots:
void sequencerTriggerSample(int index);
private slots:
void showSettings();
void chokeTriggered(int choke);
void updateWidgets();
void stopAll();
@@ -53,5 +54,7 @@ private:
const std::unique_ptr<Ui::DrumPadSamplesWidget> m_ui;
DrumMachineSettings *m_settings{};
drumpad_presets::Preset m_preset;
};

View File

@@ -73,6 +73,19 @@
</item>
<item row="0" column="0" colspan="9">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButtonSettings">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⚙️</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
@@ -87,14 +100,17 @@
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<widget class="MidiButton" name="pushButtonSwap">
<property name="text">
<string>Swap left/right</string>
<string>Swap Left/Right</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonStopAll">
<widget class="MidiButton" name="pushButtonStopAll">
<property name="text">
<string>Stop all</string>
</property>
@@ -337,6 +353,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MidiButton</class>
<extends>QPushButton</extends>
<header>widgets/midibutton.h</header>
</customwidget>
<customwidget>
<class>DrumPadSampleWidget</class>
<extends>QFrame</extends>

View File

@@ -20,7 +20,8 @@ QString toString(bool value) { return value?"true":"false"; }
DrumPadSampleWidget::DrumPadSampleWidget(QWidget *parent) :
QFrame{parent},
m_ui{std::make_unique<Ui::DrumPadSampleWidget>()}
m_ui{std::make_unique<Ui::DrumPadSampleWidget>()},
m_player{this}
{
m_ui->setupUi(this);
@@ -161,17 +162,20 @@ void DrumPadSampleWidget::unsendColor()
{
m_sendColors = false;
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlay->learnSetting().channel,
.cmd = m_ui->pushButtonPlay->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlay->learnSetting().note,
.velocity = 0
.velocity = color
});
m_lastMidiColor = 0;
m_lastMidiColor = color;
}
void DrumPadSampleWidget::sendColor()
void DrumPadSampleWidget::sendColor(bool force)
{
m_sendColors = true;
@@ -181,25 +185,24 @@ void DrumPadSampleWidget::sendColor()
{
const auto &color = *m_file->color;
if (color == "purple")
newColor = m_player.playing() ? 43 : 18;
newColor = m_player.playing() ? 56 : 59;
else if (color == "red")
newColor = m_player.playing() ? 3 : 1;
newColor = m_player.playing() ? 4 : 7;
else if (color == "yellow")
newColor = m_player.playing() ? 58 : 33;
newColor = m_player.playing() ? 12 : 15;
else if (color == "green")
newColor = m_player.playing() ? 56 : 16;
newColor = m_player.playing() ? 20 : 23;
else if (color == "blue")
newColor = m_player.playing() ? 49 : 51;
newColor = m_player.playing() ? 44 : 47;
else
goto noColor;
newColor = m_player.playing() ? 127 : 1;
}
else
{
noColor:
newColor = 0;
}
if (newColor != m_lastMidiColor)
if (force || newColor != m_lastMidiColor)
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlay->learnSetting().channel,
@@ -253,7 +256,7 @@ void DrumPadSampleWidget::updateStatus()
}
if (m_sendColors)
sendColor();
sendColor(false);
if (m_reply)
{

View File

@@ -52,7 +52,7 @@ public:
void midiReceived(const midi::MidiMessage &message);
void unsendColor();
void sendColor();
void sendColor(bool force);
signals:
void chokeTriggered(int choke);

View File

@@ -1,5 +1,5 @@
#include "sequencerwidget.h"
#include "ui_sequencerwidget.h"
#include "drumpadsequencerwidget.h"
#include "ui_drumpadsequencerwidget.h"
#include <algorithm>
@@ -9,80 +9,85 @@
#include "drummachinesettings.h"
#include "midicontainers.h"
SequencerWidget::SequencerWidget(QWidget *parent) :
DrumPadSequencerWidget::DrumPadSequencerWidget(QWidget *parent) :
QWidget{parent},
m_ui{std::make_unique<Ui::SequencerWidget>()}
m_ui{std::make_unique<Ui::DrumPadSequencerWidget>()},
m_timer{this}
{
m_ui->setupUi(this);
connect(m_ui->spinBoxTempo, qOverload<int>(&QSpinBox::valueChanged), this, &SequencerWidget::tempoChanged);
connect(m_ui->spinBoxTempo, qOverload<int>(&QSpinBox::valueChanged), this, &DrumPadSequencerWidget::tempoChanged);
connect(m_ui->comboBoxSequence, qOverload<int>(&QComboBox::currentIndexChanged), this, &SequencerWidget::sequenceSelected);
connect(m_ui->comboBoxSequence, qOverload<int>(&QComboBox::currentIndexChanged), this, &DrumPadSequencerWidget::sequenceSelected);
connect(m_ui->pushButtonUp, &QAbstractButton::pressed, this, &SequencerWidget::selectPrevSequence);
connect(m_ui->pushButtonDown, &QAbstractButton::pressed, this, &SequencerWidget::selectNextSequence);
connect(m_ui->pushButtonPlayPause, &QAbstractButton::pressed, this, &SequencerWidget::playPause);
connect(m_ui->pushButtonStop, &QAbstractButton::pressed, this, &SequencerWidget::stop);
connect(m_ui->pushButtonUp, &QAbstractButton::pressed, this, &DrumPadSequencerWidget::selectPrevSequence);
connect(m_ui->pushButtonDown, &QAbstractButton::pressed, this, &DrumPadSequencerWidget::selectNextSequence);
connect(m_ui->pushButtonPlayPause, &QAbstractButton::pressed, this, &DrumPadSequencerWidget::playPause);
connect(m_ui->pushButtonStop, &QAbstractButton::pressed, this, &DrumPadSequencerWidget::stop);
connect(m_ui->horizontalSlider, &QSlider::valueChanged, this, [=](int value){ m_pos = value; updateStatusLabel(); });
connect(&m_timer, &QTimer::timeout, this, &SequencerWidget::timeout);
connect(&m_timer, &QTimer::timeout, this, &DrumPadSequencerWidget::timeout);
m_timer.setTimerType(Qt::PreciseTimer);
updateStatusLabel();
}
SequencerWidget::~SequencerWidget() = default;
DrumPadSequencerWidget::~DrumPadSequencerWidget() = default;
void SequencerWidget::loadSettings(DrumMachineSettings &settings)
void DrumPadSequencerWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
m_ui->pushButtonUp->setLearnSetting(settings.drumpadPrevSequence());
m_ui->pushButtonDown->setLearnSetting(settings.drumpadNextSequence());
m_ui->pushButtonPlayPause->setLearnSetting(settings.drumpadPlayPause());
m_ui->pushButtonStop->setLearnSetting(settings.drumpadStop());
m_ui->pushButtonStop->setLearnSetting(settings.drumpadStopSequence());
connect(m_ui->pushButtonUp, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadPrevSequence);
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadNextSequence);
connect(m_ui->pushButtonPlayPause, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadPlayPause);
connect(m_ui->pushButtonStop, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadStop);
connect(m_ui->pushButtonStop, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadStopSequence);
}
void SequencerWidget::unsendColors()
void DrumPadSequencerWidget::unsendColors()
{
m_sendColors = false;
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = 0
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = 0
.velocity = color
});
}
void SequencerWidget::sendColors()
void DrumPadSequencerWidget::sendColors()
{
m_sendColors = true;
@@ -91,32 +96,32 @@ void SequencerWidget::sendColors()
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 127
.velocity = m_settings ? m_settings->drumpadColorPrevSequence() : quint8{127}
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 127
.velocity = m_settings ? m_settings->drumpadColorNextSequence() : quint8{127}
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = 60
.velocity = m_settings ? m_settings->drumpadColorPlayPause() : quint8{3}
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = 3
.velocity = m_settings ? m_settings->drumpadColorStopSequence() : quint8{60}
});
}
void SequencerWidget::setPreset(const drumpad_presets::Preset &preset)
void DrumPadSequencerWidget::setPreset(const drumpad_presets::Preset &preset)
{
if (preset.tempo)
m_ui->spinBoxTempo->setValue(*preset.tempo);
@@ -155,7 +160,7 @@ void SequencerWidget::setPreset(const drumpad_presets::Preset &preset)
sequenceSelected();
}
void SequencerWidget::midiReceived(const midi::MidiMessage &message)
void DrumPadSequencerWidget::midiReceived(const midi::MidiMessage &message)
{
m_ui->pushButtonUp->midiReceived(message);
m_ui->pushButtonDown->midiReceived(message);
@@ -163,7 +168,7 @@ void SequencerWidget::midiReceived(const midi::MidiMessage &message)
m_ui->pushButtonStop->midiReceived(message);
}
void SequencerWidget::playPause()
void DrumPadSequencerWidget::playPause()
{
if (m_timer.isActive())
{
@@ -177,7 +182,7 @@ void SequencerWidget::playPause()
}
}
void SequencerWidget::stop()
void DrumPadSequencerWidget::stop()
{
m_timer.stop();
m_ui->pushButtonPlayPause->setText(tr(""));
@@ -186,12 +191,12 @@ void SequencerWidget::stop()
updateStatusLabel();
}
void SequencerWidget::tempoChanged(int tempo)
void DrumPadSequencerWidget::tempoChanged(int tempo)
{
m_timer.setInterval(1000. * 60. / tempo / 4.);
}
void SequencerWidget::sequenceSelected()
void DrumPadSequencerWidget::sequenceSelected()
{
const auto index = m_ui->comboBoxSequence->currentIndex();
@@ -210,7 +215,7 @@ void SequencerWidget::sequenceSelected()
updateStatusLabel();
}
void SequencerWidget::timeout()
void DrumPadSequencerWidget::timeout()
{
if (m_selectedSequence && m_selectedSequence->pads)
{
@@ -244,18 +249,18 @@ void SequencerWidget::timeout()
updateStatusLabel();
}
void SequencerWidget::updateStatusLabel()
void DrumPadSequencerWidget::updateStatusLabel()
{
m_ui->labelStatus->setText(QString{"%0 / %1"}.arg(m_pos+1).arg(m_selectedSequence && m_selectedSequence->sequencerSize ? *m_selectedSequence->sequencerSize-1 : -1));
}
void SequencerWidget::selectPrevSequence()
void DrumPadSequencerWidget::selectPrevSequence()
{
if (const auto index = m_ui->comboBoxSequence->currentIndex(); index > 0)
m_ui->comboBoxSequence->setCurrentIndex(index - 1);
}
void SequencerWidget::selectNextSequence()
void DrumPadSequencerWidget::selectNextSequence()
{
if (const auto index = m_ui->comboBoxSequence->currentIndex(); index + 1 < m_ui->comboBoxSequence->count())
m_ui->comboBoxSequence->setCurrentIndex(index + 1);

View File

@@ -8,18 +8,18 @@
#include <QTimer>
class QLabel;
namespace Ui { class SequencerWidget; }
namespace Ui { class DrumPadSequencerWidget; }
namespace drumpad_presets { struct Preset; struct Sequence; }
class DrumMachineSettings;
namespace midi { struct MidiMessage; }
class SequencerWidget : public QWidget
class DrumPadSequencerWidget : public QWidget
{
Q_OBJECT
public:
explicit SequencerWidget(QWidget *parent = nullptr);
~SequencerWidget() override;
explicit DrumPadSequencerWidget(QWidget *parent = nullptr);
~DrumPadSequencerWidget() override;
void loadSettings(DrumMachineSettings &settings);
void unsendColors();
@@ -48,7 +48,9 @@ private slots:
void selectNextSequence();
private:
const std::unique_ptr<Ui::SequencerWidget> m_ui;
const std::unique_ptr<Ui::DrumPadSequencerWidget> m_ui;
DrumMachineSettings *m_settings{};
std::vector<drumpad_presets::Sequence> m_sequences;
const drumpad_presets::Sequence *m_selectedSequence{};

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SequencerWidget</class>
<widget class="QWidget" name="SequencerWidget">
<class>DrumPadSequencerWidget</class>
<widget class="QWidget" name="DrumPadSequencerWidget">
<property name="geometry">
<rect>
<x>0</x>

View File

@@ -0,0 +1,102 @@
#include "drumpadsettingsdialog.h"
#include "ui_drumpadsettingsdialog.h"
#include <QDebug>
#include <QAbstractButton>
#include "drummachinesettings.h"
DrumPadSettingsDialog::DrumPadSettingsDialog(DrumMachineSettings &settings, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::DrumPadSettingsDialog>()},
m_settings{settings}
{
m_ui->setupUi(this);
connect(m_ui->buttonBox, &QDialogButtonBox::clicked, this, &DrumPadSettingsDialog::buttonClicked);
resetFields();
}
DrumPadSettingsDialog::~DrumPadSettingsDialog() = default;
void DrumPadSettingsDialog::accept()
{
if (const quint8 colorPrevPreset = m_ui->spinBoxColorPrevPreset->value();
m_settings.drumpadColorPrevPreset() != colorPrevPreset)
m_settings.setDrumpadColorPrevPreset(colorPrevPreset);
if (const quint8 colorNextPreset = m_ui->spinBoxColorNextPreset->value();
m_settings.drumpadColorNextPreset() != colorNextPreset)
m_settings.setDrumpadColorNextPreset(colorNextPreset);
if (const quint8 colorPrevSequence = m_ui->spinBoxColorPrevSequence->value();
m_settings.drumpadColorPrevSequence() != colorPrevSequence)
m_settings.setDrumpadColorPrevSequence(colorPrevSequence);
if (const quint8 colorNextSequence = m_ui->spinBoxColorNextSequence->value();
m_settings.drumpadColorNextSequence() != colorNextSequence)
m_settings.setDrumpadColorNextSequence(colorNextSequence);
if (const quint8 colorPlayPause = m_ui->spinBoxColorPlayPause->value();
m_settings.drumpadColorPlayPause() != colorPlayPause)
m_settings.setDrumpadColorPlayPause(colorPlayPause);
if (const quint8 colorStopSequence = m_ui->spinBoxColorStopSequence->value();
m_settings.drumpadColorStopSequence() != colorStopSequence)
m_settings.setDrumpadColorStopSequence(colorStopSequence);
if (const quint8 colorSwap = m_ui->spinBoxColorSwap->value();
m_settings.drumpadColorSwap() != colorSwap)
m_settings.setDrumpadColorSwap(colorSwap);
if (const quint8 colorStopAll = m_ui->spinBoxColorStopAll->value();
m_settings.drumpadColorStopAll() != colorStopAll)
m_settings.setDrumpadColorStopAll(colorStopAll);
QDialog::accept();
}
void DrumPadSettingsDialog::buttonClicked(QAbstractButton *button)
{
if (!button)
{
qWarning() << "invalid button";
return;
}
switch (m_ui->buttonBox->standardButton(button))
{
case QDialogButtonBox::Reset:
resetFields();
return;
case QDialogButtonBox::RestoreDefaults:
restoreDefaults();
return;
default:;
}
}
void DrumPadSettingsDialog::resetFields()
{
m_ui->spinBoxColorPrevPreset->setValue(m_settings.drumpadColorPrevPreset());
m_ui->spinBoxColorNextPreset->setValue(m_settings.drumpadColorNextPreset());
m_ui->spinBoxColorPrevSequence->setValue(m_settings.drumpadColorPrevSequence());
m_ui->spinBoxColorNextSequence->setValue(m_settings.drumpadColorNextSequence());
m_ui->spinBoxColorPlayPause->setValue(m_settings.drumpadColorPlayPause());
m_ui->spinBoxColorStopSequence->setValue(m_settings.drumpadColorStopSequence());
m_ui->spinBoxColorSwap->setValue(m_settings.drumpadColorSwap());
m_ui->spinBoxColorStopAll->setValue(m_settings.drumpadColorStopAll());
}
void DrumPadSettingsDialog::restoreDefaults()
{
m_ui->spinBoxColorPrevPreset->setValue(m_settings.defaultDrumpadColorPrevPreset());
m_ui->spinBoxColorNextPreset->setValue(m_settings.defaultDrumpadColorNextPreset());
m_ui->spinBoxColorPrevSequence->setValue(m_settings.defaultDrumpadColorPrevSequence());
m_ui->spinBoxColorNextSequence->setValue(m_settings.defaultDrumpadColorNextSequence());
m_ui->spinBoxColorPlayPause->setValue(m_settings.defaultDrumpadColorPlayPause());
m_ui->spinBoxColorStopSequence->setValue(m_settings.defaultDrumpadColorStopSequence());
m_ui->spinBoxColorSwap->setValue(m_settings.defaultDrumpadColorSwap());
m_ui->spinBoxColorStopAll->setValue(m_settings.defaultDrumpadColorStopAll());
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class DrumPadSettingsDialog; }
class DrumMachineSettings;
class QAbstractButton;
class DrumPadSettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit DrumPadSettingsDialog(DrumMachineSettings &settings, QWidget *parent = nullptr);
~DrumPadSettingsDialog() override;
public slots:
void accept() override;
private slots:
void buttonClicked(QAbstractButton *button);
void resetFields();
void restoreDefaults();
private:
const std::unique_ptr<Ui::DrumPadSettingsDialog> m_ui;
DrumMachineSettings &m_settings;
};

View File

@@ -0,0 +1,340 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DrumPadSettingsDialog</class>
<widget class="QDialog" name="DrumPadSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>326</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelColorPrevPreset">
<property name="text">
<string>Color Prev Preset:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorPrevPreset</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelColorNextPreset">
<property name="text">
<string>Color Next Preset:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorNextPreset</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelColorPrevSequence">
<property name="text">
<string>Color Prev Sequence:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorPrevSequence</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelColorNextSequence">
<property name="text">
<string>Color Next Sequence:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorNextSequence</cstring>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelColorPlayPause">
<property name="text">
<string>Color Play Pause:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorPlayPause</cstring>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelColorStopSequence">
<property name="text">
<string>Color Stop Sequence:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorStopSequence</cstring>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelColorSwap">
<property name="text">
<string>Color Swap:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorSwap</cstring>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelColorStopAll">
<property name="text">
<string>Color Stop All:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorStopAll</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBoxColorPrevPreset">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="spinBoxColorNextPreset">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="spinBoxColorPrevSequence">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="spinBoxColorNextSequence">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QSpinBox" name="spinBoxColorPlayPause">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QSpinBox" name="spinBoxColorStopSequence">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QSpinBox" name="spinBoxColorSwap">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QSpinBox" name="spinBoxColorStopAll">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DrumPadSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DrumPadSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -14,7 +14,10 @@
DrumPadWidget::DrumPadWidget(QWidget *parent) :
QSplitter{parent},
m_ui{std::make_unique<Ui::DrumPadWidget>()}
m_ui{std::make_unique<Ui::DrumPadWidget>()},
m_presetsModel{this},
m_presetsProxyModel{this},
m_filesModel{this}
{
m_ui->setupUi(this);
@@ -22,10 +25,10 @@ DrumPadWidget::DrumPadWidget(QWidget *parent) :
connect(m_ui->pushButtonDown, &QAbstractButton::pressed, this, &DrumPadWidget::selectNextPreset);
connect(m_ui->pushButtonRefresh, &QAbstractButton::pressed, this, &DrumPadWidget::loadPresets);
connect(m_ui->sequencerWidget, &SequencerWidget::sendMidi, this, &DrumPadWidget::sendMidi);
connect(m_ui->sequencerWidget, &DrumPadSequencerWidget::sendMidi, this, &DrumPadWidget::sendMidi);
connect(m_ui->samplesWidget, &DrumPadSamplesWidget::sendMidi, this, &DrumPadWidget::sendMidi);
connect(m_ui->sequencerWidget, &SequencerWidget::triggerSample, m_ui->samplesWidget, &DrumPadSamplesWidget::sequencerTriggerSample);
connect(m_ui->sequencerWidget, &DrumPadSequencerWidget::triggerSample, m_ui->samplesWidget, &DrumPadSamplesWidget::sequencerTriggerSample);
m_presetsProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
m_presetsProxyModel.setSortRole(Qt::EditRole);
@@ -76,19 +79,21 @@ void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
void DrumPadWidget::unsendColors()
{
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
.velocity = color
});
m_ui->sequencerWidget->unsendColors();
@@ -102,14 +107,14 @@ void DrumPadWidget::sendColors()
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 127
.velocity = m_settings ? m_settings->drumpadColorPrevPreset() : quint8{127}
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 127
.velocity = m_settings ? m_settings->drumpadColorNextPreset() : quint8{127}
});
m_ui->sequencerWidget->sendColors();

View File

@@ -9,7 +9,6 @@
#include "drumpadfilesmodel.h"
namespace Ui { class DrumPadWidget; }
class SequencerWidget;
class QModelIndex;
class QNetworkAccessManager;
class QThread;

View File

@@ -107,7 +107,7 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="SequencerWidget" name="sequencerWidget" native="true"/>
<widget class="DrumPadSequencerWidget" name="sequencerWidget" native="true"/>
<widget class="DrumPadSamplesWidget" name="samplesWidget" native="true"/>
</widget>
</widget>
@@ -130,9 +130,9 @@
<container>1</container>
</customwidget>
<customwidget>
<class>SequencerWidget</class>
<class>DrumPadSequencerWidget</class>
<extends>QWidget</extends>
<header>widgets/sequencerwidget.h</header>
<header>widgets/drumpadsequencerwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View File

@@ -5,7 +5,8 @@
LoopStationPresetDetailWidget::LoopStationPresetDetailWidget(QWidget *parent) :
QScrollArea{parent},
m_ui{std::make_unique<Ui::LoopStationPresetDetailWidget>()}
m_ui{std::make_unique<Ui::LoopStationPresetDetailWidget>()},
m_tagsModel{this}
{
m_ui->setupUi(this);

View File

@@ -1,14 +1,20 @@
#include "loopstationsampleswidget.h"
#include "ui_loopstationsampleswidget.h"
#include <algorithm>
#include "loopstationpresets.h"
#include "drummachinesettings.h"
LoopStationSamplesWidget::LoopStationSamplesWidget(QWidget *parent) :
QWidget{parent},
m_ui{std::make_unique<Ui::LoopStationSamplesWidget>()}
m_ui{std::make_unique<Ui::LoopStationSamplesWidget>()},
m_timer{this}
{
m_ui->setupUi(this);
connect(m_ui->pushButtonSettings, &QAbstractButton::pressed, this, &LoopStationSamplesWidget::showSettings);
connect(m_ui->spinBoxBpm, qOverload<int>(&QSpinBox::valueChanged), this, &LoopStationSamplesWidget::tempoChanged);
connect(m_ui->pushButtonPlayPause, &QAbstractButton::pressed, this, &LoopStationSamplesWidget::playPausePressed);
@@ -23,7 +29,7 @@ LoopStationSamplesWidget::LoopStationSamplesWidget(QWidget *parent) :
{
widget.setPadNr(padNr++);
connect(&widget, &LoopStationSampleWidget::sendMidi, this, &LoopStationSamplesWidget::sendMidi);
connect(&widget, &LoopStationSampleWidget::loopEnabled, this, &LoopStationSamplesWidget::loopEnabled);
connect(&widget, &LoopStationSampleWidget::loopEnabledChanged, this, &LoopStationSamplesWidget::loopEnabledChanged);
}
constexpr const auto setCategories = [](auto category, auto *widget0, auto *widget1, auto *widget2, auto *widget3, auto *widget4, auto *widget5, auto *widget6, auto *widget7){
@@ -54,6 +60,14 @@ LoopStationSamplesWidget::~LoopStationSamplesWidget() = default;
void LoopStationSamplesWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
m_ui->pushButtonPlayPause->setLearnSetting(settings.loopstationPlayPause());
m_ui->pushButtonStop->setLearnSetting(settings.loopstationStop());
connect(m_ui->pushButtonPlayPause, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setLoopstationPlayPause);
connect(m_ui->pushButtonStop, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setLoopstationStop);
for (LoopStationSampleWidget &widget : getWidgets())
widget.loadSettings(settings);
}
@@ -83,6 +97,9 @@ void LoopStationSamplesWidget::setPreset(const loopstation_presets::Preset &pres
void LoopStationSamplesWidget::midiReceived(const midi::MidiMessage &message)
{
m_ui->pushButtonPlayPause->midiReceived(message);
m_ui->pushButtonStop->midiReceived(message);
for (LoopStationSampleWidget &widget : getWidgets())
widget.midiReceived(message);
}
@@ -106,15 +123,52 @@ void LoopStationSamplesWidget::injectDecodingThread(QThread &thread)
}
void LoopStationSamplesWidget::unsendColors()
{
{
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = color
});
for (LoopStationSampleWidget &widget : getWidgets())
widget.unsendColor();
}
void LoopStationSamplesWidget::sendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = 3
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = 60
});
for (LoopStationSampleWidget &widget : getWidgets())
widget.sendColor();
widget.sendColor(true);
}
void LoopStationSamplesWidget::showSettings()
{
}
void LoopStationSamplesWidget::timeout()
@@ -143,34 +197,55 @@ void LoopStationSamplesWidget::tempoChanged(int tempo)
m_timer.setInterval(1000. * 60. / tempo);
}
void LoopStationSamplesWidget::loopEnabled(quint8 category)
void LoopStationSamplesWidget::loopEnabledChanged(bool loopEnabled, quint8 category)
{
for (LoopStationSampleWidget &widget : getWidgets())
if (loopEnabled)
{
if (widget.category() != category)
continue;
if (&widget == sender())
continue;
widget.setLoopEnabled(false);
}
if (!m_timer.isActive())
{
m_pos = 0;
m_ui->horizontalSlider->setValue(m_pos);
m_timer.start();
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
{
if (widget.category() != category)
continue;
if (&widget == sender())
continue;
widget.setLoopEnabled(false);
}
if (!m_timer.isActive())
{
m_pos = 0;
m_ui->horizontalSlider->setValue(m_pos);
m_timer.start();
m_ui->pushButtonPlayPause->setText(tr("▮▮"));
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
}
}
else
{
const auto widgets = getWidgets();
if (m_timer.isActive() && std::none_of(std::begin(widgets), std::end(widgets), [](const LoopStationSampleWidget &widget){
return widget.loopEnabled();
}))
{
m_timer.stop();
m_ui->pushButtonPlayPause->setText(tr(""));
m_pos = 0;
m_ui->horizontalSlider->setValue(m_pos);
}
}
}
void LoopStationSamplesWidget::playPausePressed()
{
if (m_timer.isActive())
{
m_timer.stop();
m_ui->pushButtonPlayPause->setText(tr(""));
}
else
{
m_timer.start();
m_ui->pushButtonPlayPause->setText(tr("▮▮"));
if (m_pos == 0)
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
@@ -180,6 +255,7 @@ void LoopStationSamplesWidget::playPausePressed()
void LoopStationSamplesWidget::stopPressed()
{
m_timer.stop();
m_ui->pushButtonPlayPause->setText(tr(""));
for (LoopStationSampleWidget &widget : getWidgets())
{
widget.setLoopEnabled(false);

View File

@@ -22,7 +22,7 @@ class LoopStationSamplesWidget : public QWidget
public:
explicit LoopStationSamplesWidget(QWidget *parent = nullptr);
~LoopStationSamplesWidget();
~LoopStationSamplesWidget() override;
void loadSettings(DrumMachineSettings &settings);
@@ -42,9 +42,10 @@ signals:
void sendMidi(const midi::MidiMessage &midiMsg);
private slots:
void showSettings();
void timeout();
void tempoChanged(int tempo);
void loopEnabled(quint8 category);
void loopEnabledChanged(bool loopEnabled, quint8 category);
void playPausePressed();
void stopPressed();
@@ -53,6 +54,8 @@ private:
const std::unique_ptr<Ui::LoopStationSamplesWidget> m_ui;
DrumMachineSettings *m_settings{};
QTimer m_timer;
quint8 m_pos{};

View File

@@ -558,6 +558,19 @@
</item>
<item row="0" column="0" colspan="12">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButtonSettings">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⚙️</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelBpm">
<property name="text">
@@ -579,16 +592,28 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonPlayPause">
<widget class="MidiButton" name="pushButtonPlayPause">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Play/Pause</string>
<string></string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonStop">
<widget class="MidiButton" name="pushButtonStop">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Stop</string>
<string></string>
</property>
</widget>
</item>
@@ -629,6 +654,11 @@
<header>widgets/loopstationsamplewidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>MidiButton</class>
<extends>QPushButton</extends>
<header>widgets/midibutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@@ -15,16 +15,15 @@
LoopStationSampleWidget::LoopStationSampleWidget(QWidget *parent) :
QFrame{parent},
m_ui{std::make_unique<Ui::LoopStationSampleWidget>()}
m_ui{std::make_unique<Ui::LoopStationSampleWidget>()},
m_player{this}
{
m_ui->setupUi(this);
connect(&m_player, &AudioPlayer::playingChanged, this, &LoopStationSampleWidget::updateStatus);
connect(m_ui->pushButtonPlay, &QAbstractButton::toggled, this, [this](bool toggled){
if (!toggled)
return;
emit loopEnabled(m_category);
emit loopEnabledChanged(toggled, m_category);
});
updateStatus();
@@ -99,24 +98,27 @@ void LoopStationSampleWidget::unsendColor()
{
m_sendColors = false;
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlay->learnSetting().channel,
.cmd = m_ui->pushButtonPlay->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlay->learnSetting().note,
.velocity = 0
.velocity = color
});
m_lastMidiColor = 0;
m_lastMidiColor = color;
}
void LoopStationSampleWidget::sendColor()
void LoopStationSampleWidget::sendColor(bool force)
{
m_sendColors = true;
quint8 newColor;
if (false) // testing colors on launchpad mk2
newColor = m_padNr;
newColor = m_padNr + 48;
else
{
if (m_player.buffer().isValid())
@@ -134,16 +136,15 @@ void LoopStationSampleWidget::sendColor()
else if (m_category == 5)
newColor = m_player.playing() ? 52 : 55; // pink
else
goto noColor;
newColor = m_player.playing() ? 4 : 7; // red
}
else
{
noColor:
newColor = 0;
}
}
if (newColor != m_lastMidiColor)
if (force || newColor != m_lastMidiColor)
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlay->learnSetting().channel,
@@ -156,12 +157,17 @@ noColor:
}
}
bool LoopStationSampleWidget::loopEnabled() const
{
return m_ui->pushButtonPlay->isChecked();
}
void LoopStationSampleWidget::timeout()
{
if (m_ui->pushButtonPlay->isChecked())
{
// if is not playing or position > 90%
if (!m_player.playing() || m_player.position() >= m_player.buffer().frameCount() * 9 / 10)
// if is not playing or position > 80%
if (!m_player.playing() || m_player.position() >= m_player.buffer().frameCount() * 8 / 10)
m_player.restart();
}
else
@@ -225,7 +231,7 @@ void LoopStationSampleWidget::updateStatus()
}
if (m_sendColors)
sendColor();
sendColor(false);
if (m_reply)
{

View File

@@ -41,7 +41,9 @@ public:
void midiReceived(const midi::MidiMessage &message);
void unsendColor();
void sendColor();
void sendColor(bool force);
bool loopEnabled() const;
public slots:
void timeout();
@@ -51,7 +53,7 @@ public slots:
signals:
void startDecoding(std::shared_ptr<QIODevice> device);
void sendMidi(const midi::MidiMessage &midiMsg);
void loopEnabled(quint8 category);
void loopEnabledChanged(bool loopEnabled, quint8 category);
private slots:
void updateStatus();

View File

@@ -70,19 +70,21 @@ void LoopStationWidget::loadSettings(DrumMachineSettings &settings)
void LoopStationWidget::unsendColors()
{
const quint8 color = m_settings ? m_settings->colorOff() : quint8{0};
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
.velocity = color
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
.velocity = color
});
m_ui->samplesWidget->unsendColors();

View File

@@ -27,9 +27,13 @@ int paCallback(const void *inputBuffer, void *outputBuffer,
MainWindow::MainWindow(QWidget *parent) :
QMainWindow{parent},
m_ui{std::make_unique<Ui::MainWindow>()},
m_settings{this},
m_paStream{nullptr, DummyDeleter},
m_midiIn{RtMidi::UNSPECIFIED, "DrumMachine"},
m_midiOut{RtMidi::UNSPECIFIED, "DrumMachine"}
m_midiIn{RtMidi::UNSPECIFIED, "DrumMachine", 100, this},
m_midiOut{RtMidi::UNSPECIFIED, "DrumMachine", this},
m_networkAccessManager{this},
m_cache{this},
m_decoderThread{this}
{
m_ui->setupUi(this);
@@ -58,10 +62,15 @@ MainWindow::MainWindow(QWidget *parent) :
updateAudioDevices();
connect(m_ui->pushButtonRefreshAudioDevices, &QAbstractButton::pressed, this, &MainWindow::updateAudioDevices);
m_ui->spinBoxBufferSize->setValue(m_settings.framesPerBuffer());
if (const auto &lastAudioDevice = m_settings.lastAudioDevice(); !lastAudioDevice.isEmpty())
{
if (const auto index = m_ui->comboBoxAudioDevice->findText(lastAudioDevice); index >= 0)
{
m_ui->comboBoxAudioDevice->setCurrentIndex(index);
if (m_settings.autoOpenAudioDevice())
openAudioDevice();
}
else
goto paDefault;
}
@@ -70,7 +79,6 @@ MainWindow::MainWindow(QWidget *parent) :
paDefault:
m_ui->comboBoxAudioDevice->setCurrentIndex(Pa_GetDefaultOutputDevice());
}
m_ui->spinBoxBufferSize->setValue(m_settings.framesPerBuffer());
connect(m_ui->pushButtonAudioDevice, &QAbstractButton::pressed, this, &MainWindow::openAudioDevice);
updateMidiInDevices();
@@ -78,7 +86,11 @@ paDefault:
if (const auto &lastMidiInDevice = m_settings.lastMidiInDevice(); !lastMidiInDevice.isEmpty())
{
if (const auto index = m_ui->comboBoxMidiIn->findText(lastMidiInDevice); index >= 0)
{
m_ui->comboBoxMidiIn->setCurrentIndex(index);
if (m_settings.autoOpenMidiIn())
openMidiInDevice();
}
}
connect(m_ui->pushButtonMidiIn, &QAbstractButton::pressed, this, &MainWindow::openMidiInDevice);
@@ -87,7 +99,11 @@ paDefault:
if (const auto &lastMidiOutDevice = m_settings.lastMidiOutDevice(); !lastMidiOutDevice.isEmpty())
{
if (const auto index = m_ui->comboBoxMidiOut->findText(lastMidiOutDevice); index >= 0)
{
m_ui->comboBoxMidiOut->setCurrentIndex(index);
if (m_settings.autoOpenMidiOut())
openMidiOutDevice();
}
}
connect(m_ui->pushButtonMidiOut, &QAbstractButton::pressed, this, &MainWindow::openMidiOutDevice);
@@ -145,12 +161,19 @@ void MainWindow::openAudioDevice()
{
m_paStream = nullptr;
m_ui->comboBoxAudioDevice->setEnabled(true);
m_ui->pushButtonRefreshAudioDevices->setEnabled(true);
m_ui->spinBoxBufferSize->setEnabled(true);
m_ui->pushButtonAudioDevice->setText(tr("Open"));
m_settings.setAutoOpenAudioDevice(false);
}
else
{
PaDeviceIndex index = m_ui->comboBoxAudioDevice->currentIndex();
if (index < 0)
{
QMessageBox::warning(this, tr("No audio device selected!"), tr("No audio device selected!"));
return;
}
const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(index);
@@ -166,7 +189,7 @@ void MainWindow::openAudioDevice()
if (PaError err = Pa_OpenStream(&stream, NULL, &outputParameters, frameRate, m_ui->spinBoxBufferSize->value(), paNoFlag, &paCallback, this); err != paNoError)
{
QMessageBox::warning(this, tr("Error opening stream!"), tr("Error opening stream!") + "\n\n" + Pa_GetErrorText(err));
QMessageBox::warning(this, tr("Error opening audio device!"), tr("Error opening audio device!") + "\n\n" + Pa_GetErrorText(err));
return;
}
@@ -175,13 +198,13 @@ void MainWindow::openAudioDevice()
if (PaError err = Pa_SetStreamFinishedCallback(smartPtr.get(), &paStreamFinished); err != paNoError)
{
QMessageBox::warning(this, tr("Error setting finished callback!"), tr("Error setting finished callback!") + "\n\n" + Pa_GetErrorText(err));
QMessageBox::warning(this, tr("Error opening audio device!"), tr("Error setting finished callback!") + "\n\n" + Pa_GetErrorText(err));
return;
}
if (PaError err = Pa_StartStream(smartPtr.get()); err != paNoError)
{
QMessageBox::warning(this, tr("Error starting stream!"), tr("Error starting stream!") + "\n\n" + Pa_GetErrorText(err));
QMessageBox::warning(this, tr("Error opening audio device!"), tr("Error starting stream!") + "\n\n" + Pa_GetErrorText(err));
return;
}
@@ -190,51 +213,100 @@ void MainWindow::openAudioDevice()
m_paStream = std::move(smartPtr);
m_ui->comboBoxAudioDevice->setEnabled(false);
m_ui->pushButtonRefreshAudioDevices->setEnabled(false);
m_ui->spinBoxBufferSize->setEnabled(false);
m_ui->pushButtonAudioDevice->setText(tr("Close"));
m_settings.setLastAudioDevice(m_ui->comboBoxAudioDevice->currentText());
m_settings.setFramesPerBuffer(m_ui->spinBoxBufferSize->value());
m_settings.setAutoOpenAudioDevice(true);
}
}
void MainWindow::openMidiInDevice()
{
if (m_midiIn.isPortOpen())
{
m_midiIn.closePort();
if (m_midiIn.isPortOpen())
{
QMessageBox::warning(this, tr("Could not close midi in device!"), tr("Could not close midi in device!"));
return;
}
m_ui->comboBoxMidiIn->setEnabled(true);
m_ui->pushButtonRefreshMidiIn->setEnabled(true);
m_ui->pushButtonMidiIn->setText(tr("Open"));
m_settings.setAutoOpenMidiIn(false);
}
else
{
const auto index = m_ui->comboBoxMidiIn->currentIndex();
if (index != -1)
m_midiIn.openPort(index, "Input");
m_settings.setLastMidiInDevice(m_ui->comboBoxMidiIn->currentText());
}
if (index < 0)
{
QMessageBox::warning(this, tr("No midi in device selected!"), tr("No midi in device selected!"));
return;
}
m_ui->comboBoxMidiIn->setDisabled(m_midiIn.isPortOpen());
m_ui->pushButtonMidiIn->setText(m_midiIn.isPortOpen() ? tr("Close") : tr("Open"));
m_midiIn.openPort(index, "Input");
if (!m_midiIn.isPortOpen())
{
QMessageBox::warning(this, tr("Could not open midi in device!"), tr("Could not open midi in device!"));
return;
}
m_ui->comboBoxMidiIn->setEnabled(false);
m_ui->pushButtonRefreshMidiIn->setEnabled(false);
m_ui->pushButtonMidiIn->setText(tr("Close"));
m_settings.setLastMidiInDevice(m_ui->comboBoxMidiIn->currentText());
m_settings.setAutoOpenMidiIn(true);
}
}
void MainWindow::openMidiOutDevice()
{
if (m_midiOut.isPortOpen())
{
qDebug() << "closing port";
unsendColors(m_ui->tabWidget->currentIndex());
m_midiOut.closePort();
if (m_midiOut.isPortOpen())
{
QMessageBox::warning(this, tr("Could not close midi out device!"), tr("Could not close midi out device!"));
return;
}
m_ui->comboBoxMidiOut->setEnabled(true);
m_ui->pushButtonRefreshMidiOut->setEnabled(true);
m_ui->pushButtonMidiOut->setText(tr("Open"));
m_settings.setAutoOpenMidiOut(false);
}
else
{
const auto index = m_ui->comboBoxMidiOut->currentIndex();
if (index != -1)
if (index < 0)
{
m_midiOut.openPort(index, "Output");
m_settings.setLastMidiOutDevice(m_ui->comboBoxMidiOut->currentText());
sendColors(m_ui->tabWidget->currentIndex());
QMessageBox::warning(this, tr("No midi out device selected!"), tr("No midi out device selected!"));
return;
}
}
m_ui->comboBoxMidiOut->setDisabled(m_midiOut.isPortOpen());
m_ui->pushButtonMidiOut->setText(m_midiOut.isPortOpen() ? tr("Close") : tr("Open"));
m_midiOut.openPort(index, "Output");
if (!m_midiOut.isPortOpen())
{
QMessageBox::warning(this, tr("Could not open midi out device!"), tr("Could not open midi out device!"));
return;
}
m_ui->comboBoxMidiOut->setEnabled(false);
m_ui->pushButtonRefreshMidiOut->setEnabled(false);
m_ui->pushButtonMidiOut->setText(tr("Close"));
m_settings.setLastMidiOutDevice(m_ui->comboBoxMidiOut->currentText());
m_settings.setAutoOpenMidiOut(true);
sendColors(m_ui->tabWidget->currentIndex());
}
}
void MainWindow::midiReceived(const midi::MidiMessage &message)
@@ -322,7 +394,7 @@ void MainWindow::unsendColors(int index)
.cmd = learnSetting.cmd,
.flag = true,
.note = learnSetting.note,
.velocity = 0
.velocity = m_settings.colorOff()
});
}
@@ -347,7 +419,7 @@ void MainWindow::sendColors(int index)
.cmd = learnSetting.cmd,
.flag = true,
.note = learnSetting.note,
.velocity = 3
.velocity = m_settings.colorTabWidget()
});
}

View File

@@ -47,10 +47,18 @@ void SettingsDialog::accept()
m_settings.setCacheDir(cacheDir);
}
const auto maximumCacheSize = qint64{m_ui->spinBoxMaxCacheSize->value()} * 1024 * 1024;
if (m_settings.maximumCacheSize() != maximumCacheSize)
if (const auto maximumCacheSize = qint64{m_ui->spinBoxMaxCacheSize->value()} * 1024 * 1024;
m_settings.maximumCacheSize() != maximumCacheSize)
m_settings.setMaximumCacheSize(maximumCacheSize);
if (const quint8 colorOff = m_ui->spinBoxColorOff->value();
m_settings.colorOff() != colorOff)
m_settings.setColorOff(colorOff);
if (const quint8 colorTabWidget = m_ui->spinBoxColorTabWidget->value();
m_settings.colorTabWidget() != colorTabWidget)
m_settings.setColorTabWidget(colorTabWidget);
QDialog::accept();
}
@@ -78,12 +86,16 @@ void SettingsDialog::resetFields()
{
m_ui->lineEditCacheDir->setText(m_settings.cacheDir());
m_ui->spinBoxMaxCacheSize->setValue(m_settings.maximumCacheSize() / 1024 / 1024);
m_ui->spinBoxColorOff->setValue(m_settings.colorOff());
m_ui->spinBoxColorTabWidget->setValue(m_settings.colorTabWidget());
}
void SettingsDialog::restoreDefaults()
{
m_ui->lineEditCacheDir->setText(m_settings.defaultCacheDir());
m_ui->spinBoxMaxCacheSize->setValue(m_settings.defaultMaximumCacheSize() / 1024 / 1024);
m_ui->spinBoxColorOff->setValue(m_settings.defaultColorOff());
m_ui->spinBoxColorTabWidget->setValue(m_settings.defaultColorTabWidget());
}
void SettingsDialog::selectCacheDir()

View File

@@ -40,6 +40,16 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelMaxCacheSize">
<property name="text">
<string>Max Cache Size:</string>
</property>
<property name="buddy">
<cstring>spinBoxMaxCacheSize</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
<item>
@@ -61,16 +71,81 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelMaxCacheSize">
<item row="2" column="0">
<widget class="QLabel" name="labelColorOff">
<property name="text">
<string>Max Cache Size:</string>
<string>Color Off:</string>
</property>
<property name="buddy">
<cstring>spinBoxMaxCacheSize</cstring>
<cstring>spinBoxColorOff</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="spinBoxColorOff">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelColorOffHint">
<property name="text">
<string>Usually 0</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelColorTabWidget">
<property name="text">
<string>Color Tab Widget:</string>
</property>
<property name="buddy">
<cstring>spinBoxColorTabWidget</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="spinBoxColorTabWidget">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>

View File

@@ -16,7 +16,10 @@
TrackDeck::TrackDeck(QWidget *parent) :
QWidget{parent},
m_ui{std::make_unique<Ui::TrackDeck>()}
m_ui{std::make_unique<Ui::TrackDeck>()},
m_loopGroup{this},
m_player{this},
m_timer{this}
{
m_ui->setupUi(this);
m_ui->progressBar->hide();