Fixed midi handling for control change and implemented tab selection with midi

This commit is contained in:
2022-12-28 04:56:09 +01:00
parent 9d6c73782c
commit 629d2e6cd3
20 changed files with 481 additions and 455 deletions

View File

@@ -51,34 +51,9 @@ void DrumPadSamplesWidget::midiReceived(const midi::MidiMessage &message)
return;
}
if (message.cmd != midi::Command::NoteOn &&
message.cmd != midi::Command::NoteOff &&
message.cmd != midi::Command::ControlChange)
return;
for (DrumPadSampleWidget &widget : getWidgets())
{
if (widget.isLearning())
{
widget.learn(message.channel, message.note);
}
else if (widget.channel() == message.channel && widget.note() == message.note)
{
switch (message.cmd)
{
case midi::Command::NoteOn:
case midi::Command::ControlChange:
if (message.velocity != 0)
widget.pressed(message.velocity);
else
Q_FALLTHROUGH();
case midi::Command::NoteOff:
widget.released();
break;
default:
__builtin_unreachable();
}
}
widget.midiReceived(message);
}
}
@@ -120,7 +95,7 @@ void DrumPadSamplesWidget::sequencerTriggerSample(int index)
qDebug() << "index out of range" << index;
return;
}
widgets[index].get().pressed(127);
widgets[index].get().pressed();
}
void DrumPadSamplesWidget::chokeTriggered(int choke)

View File

@@ -30,9 +30,8 @@ DrumPadSampleWidget::DrumPadSampleWidget(QWidget *parent) :
connect(&m_player, &AudioPlayer::playingChanged, this, &DrumPadSampleWidget::updateStatus);
connect(m_ui->pushButton, &QAbstractButton::pressed, this, [this](){ pressed(127); });
connect(m_ui->pushButton, &QAbstractButton::released, this, &DrumPadSampleWidget::released);
connect(m_ui->toolButtonLearn, &QAbstractButton::pressed, this, &DrumPadSampleWidget::learnPressed);
connect(m_ui->pushButtonPlay, &QAbstractButton::pressed, this, &DrumPadSampleWidget::pressed);
connect(m_ui->pushButtonPlay, &QAbstractButton::released, this, &DrumPadSampleWidget::released);
updateStatus();
}
@@ -41,10 +40,17 @@ DrumPadSampleWidget::~DrumPadSampleWidget() = default;
void DrumPadSampleWidget::loadSettings(DrumMachineSettings &settings)
{
m_ui->channelSpinBox->setValue(settings.drumpadChannel(m_padNr));
m_ui->noteSpinBox->setValue(settings.drumpadNote(m_padNr));
m_settings = &settings;
m_ui->pushButtonPlay->setLearnSetting(m_settings->drumpadSample(m_padNr));
connect(m_ui->pushButtonPlay, &MidiButton::learnSettingChanged, this, [this](const MidiLearnSetting &learnSetting){
Q_ASSERT(m_settings);
if (m_settings)
m_settings->setDrumpadSample(m_padNr, learnSetting);
else
qWarning() << "no settings available";
});
}
void DrumPadSampleWidget::setFile(const QString &presetId, const drumpad_presets::File &file)
@@ -80,38 +86,6 @@ void DrumPadSampleWidget::setFile(const QString &presetId, const drumpad_presets
setupLabel(file.choke, m_ui->chokeLabel);
}
quint8 DrumPadSampleWidget::channel() const
{
return m_ui->channelSpinBox->value();
}
void DrumPadSampleWidget::setChannel(quint8 channel)
{
m_ui->channelSpinBox->setValue(channel);
Q_ASSERT(m_settings);
if (m_settings)
m_settings->setDrumpadChannel(m_padNr, channel);
else
qWarning() << "no settings available";
}
quint8 DrumPadSampleWidget::note() const
{
return m_ui->noteSpinBox->value();
}
void DrumPadSampleWidget::setNote(quint8 note)
{
m_ui->noteSpinBox->setValue(note);
Q_ASSERT(m_settings);
if (m_settings)
m_settings->setDrumpadNote(m_padNr, note);
else
qWarning() << "no settings available";
}
int DrumPadSampleWidget::speed() const
{
return m_ui->dialSpeed->value();
@@ -139,10 +113,8 @@ std::optional<int> DrumPadSampleWidget::choke() const
return m_file->choke;
}
void DrumPadSampleWidget::pressed(quint8 velocity)
void DrumPadSampleWidget::pressed()
{
Q_UNUSED(velocity)
m_player.restart();
if (m_file && m_file->choke && *m_file->choke)
@@ -181,61 +153,59 @@ void DrumPadSampleWidget::writeSamples(frame_t *begin, frame_t *end)
m_player.writeSamples(begin, end);
}
void DrumPadSampleWidget::learn(quint8 channel, quint8 note)
void DrumPadSampleWidget::midiReceived(const midi::MidiMessage &message)
{
setChannel(channel);
setNote(note);
if (m_learning)
learnPressed();
m_ui->pushButtonPlay->midiReceived(message);
}
void DrumPadSampleWidget::unsendColor()
{
m_sendColors = false;
midi::MidiMessage midiMsg;
midiMsg.channel = m_ui->channelSpinBox->value();
midiMsg.cmd = midi::Command::NoteOn;
midiMsg.flag = true;
midiMsg.note = m_ui->noteSpinBox->value();
midiMsg.velocity = 0;
emit sendMidi(midiMsg);
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
});
}
void DrumPadSampleWidget::sendColor()
{
m_sendColors = true;
midi::MidiMessage midiMsg;
midiMsg.channel = m_ui->channelSpinBox->value();
midiMsg.cmd = midi::Command::NoteOn;
midiMsg.flag = true;
midiMsg.note = m_ui->noteSpinBox->value();
uint8_t velocity;
if (m_file && m_file->color && m_player.buffer().isValid())
{
const auto &color = *m_file->color;
if (color == "purple")
midiMsg.velocity = m_player.playing() ? 43 : 18;
velocity = m_player.playing() ? 43 : 18;
else if (color == "red")
midiMsg.velocity = m_player.playing() ? 3 : 1;
velocity = m_player.playing() ? 3 : 1;
else if (color == "yellow")
midiMsg.velocity = m_player.playing() ? 58 : 33;
velocity = m_player.playing() ? 58 : 33;
else if (color == "green")
midiMsg.velocity = m_player.playing() ? 56 : 16;
velocity = m_player.playing() ? 56 : 16;
else if (color == "blue")
midiMsg.velocity = m_player.playing() ? 49 : 51;
velocity = m_player.playing() ? 49 : 51;
else
goto noColor;
}
else
{
noColor:
midiMsg.velocity = 0;
velocity = 0;
}
emit sendMidi(midiMsg);
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 = velocity
});
}
void DrumPadSampleWidget::updateStatus()
@@ -309,27 +279,6 @@ void DrumPadSampleWidget::decodingFinished(const QAudioBuffer &buffer)
updateStatus();
}
void DrumPadSampleWidget::learnPressed()
{
auto palette = m_ui->toolButtonLearn->palette();
if (m_learning)
{
palette.setColor(m_ui->toolButtonLearn->backgroundRole(), m_oldColor);
palette.setBrush(m_ui->toolButtonLearn->backgroundRole(), m_oldBrush);
}
else
{
m_oldColor = palette.color(m_ui->toolButtonLearn->backgroundRole());
m_oldBrush = palette.brush(m_ui->toolButtonLearn->backgroundRole());
palette.setColor(m_ui->toolButtonLearn->backgroundRole(), Qt::red);
palette.setBrush(m_ui->toolButtonLearn->backgroundRole(), Qt::red);
}
m_ui->toolButtonLearn->setPalette(palette);
m_learning = !m_learning;
}
void DrumPadSampleWidget::startRequest()
{
if (m_networkAccessManager && m_file->filename)

View File

@@ -31,12 +31,6 @@ public:
void setFile(const QString &presetId, const drumpad_presets::File &file);
quint8 channel() const;
void setChannel(quint8 channel);
quint8 note() const;
void setNote(quint8 note);
int speed() const;
void setSpeed(int speed);
@@ -45,7 +39,7 @@ public:
std::optional<int> choke() const;
void pressed(quint8 velocity);
void pressed();
void released();
void forceStop();
@@ -55,8 +49,7 @@ public:
void writeSamples(frame_t *begin, frame_t *end);
bool isLearning() const { return m_learning; }
void learn(quint8 channel, quint8 note);
void midiReceived(const midi::MidiMessage &message);
void unsendColor();
void sendColor();
@@ -70,7 +63,6 @@ private slots:
void updateStatus();
void requestFinished();
void decodingFinished(const QAudioBuffer &buffer);
void learnPressed();
private:
void startRequest();
@@ -92,9 +84,5 @@ private:
quint8 m_padNr{};
bool m_learning{};
QColor m_oldColor;
QBrush m_oldBrush;
bool m_sendColors{};
};

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>140</width>
<height>157</height>
<width>135</width>
<height>122</height>
</rect>
</property>
<property name="autoFillBackground">
@@ -59,7 +59,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="MidiButton" name="pushButton">
<widget class="MidiButton" name="pushButtonPlay">
<property name="maximumSize">
<size>
<width>32</width>
@@ -95,23 +95,6 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="channelSpinBox"/>
</item>
<item>
<widget class="QSpinBox" name="noteSpinBox"/>
</item>
<item>
<widget class="QToolButton" name="toolButtonLearn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>

View File

@@ -64,15 +64,11 @@ void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
m_ui->pushButtonUp->setChannel(m_settings->drumpadChannelPrevPreset());
m_ui->pushButtonUp->setNote(m_settings->drumpadNotePrevPreset());
m_ui->pushButtonDown->setChannel(m_settings->drumpadChannelNextPreset());
m_ui->pushButtonDown->setNote(m_settings->drumpadNoteNextPreset());
m_ui->pushButtonUp->setLearnSetting(m_settings->drumpadPrevPreset());
m_ui->pushButtonDown->setLearnSetting(m_settings->drumpadNextPreset());
connect(m_ui->pushButtonUp, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setDrumpadChannelPrevPreset);
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setDrumpadNotePrevPreset);
connect(m_ui->pushButtonDown, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setDrumpadChannelNextPreset);
connect(m_ui->pushButtonDown, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setDrumpadNoteNextPreset);
connect(m_ui->pushButtonUp, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setDrumpadPrevPreset);
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setDrumpadNextPreset);
m_ui->sequencerWidget->loadSettings(settings);
m_ui->samplesWidget->loadSettings(settings);
@@ -81,17 +77,17 @@ void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
void DrumPadWidget::unsendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
});
@@ -102,17 +98,17 @@ void DrumPadWidget::unsendColors()
void DrumPadWidget::sendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 127
});

View File

@@ -57,31 +57,27 @@ void LoopStationWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
m_ui->pushButtonUp->setChannel(m_settings->loopstationChannelPrevPreset());
m_ui->pushButtonUp->setNote(m_settings->loopstationNotePrevPreset());
m_ui->pushButtonDown->setChannel(m_settings->loopstationChannelNextPreset());
m_ui->pushButtonDown->setNote(m_settings->loopstationNoteNextPreset());
m_ui->pushButtonUp->setLearnSetting(m_settings->loopstationPrevPreset());
m_ui->pushButtonDown->setLearnSetting(m_settings->loopstationNextPreset());
connect(m_ui->pushButtonUp, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setLoopstationChannelPrevPreset);
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setLoopstationNotePrevPreset);
connect(m_ui->pushButtonDown, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setLoopstationChannelNextPreset);
connect(m_ui->pushButtonDown, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setLoopstationNoteNextPreset);
connect(m_ui->pushButtonUp, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setLoopstationPrevPreset);
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setLoopstationNextPreset);
}
void LoopStationWidget::unsendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
});
}
@@ -89,17 +85,17 @@ void LoopStationWidget::unsendColors()
void LoopStationWidget::sendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 127
});
}

View File

@@ -303,6 +303,10 @@ void MainWindow::updateMidiOutDevices()
void MainWindow::loadSettings()
{
for (int i = 0; i < m_ui->tabWidget->count(); i++)
m_ui->tabWidget->setLearnSetting(i, m_settings.tabWidget(i));
connect(m_ui->tabWidget, &MidiTabWidget::learnSettingChanged, &m_settings, &DrumMachineSettings::setTabWidget);
m_ui->drumPadWidget->loadSettings(m_settings);
m_ui->loopStationWidget->loadSettings(m_settings);
m_ui->djWidget->loadSettings(m_settings);
@@ -311,6 +315,17 @@ void MainWindow::loadSettings()
void MainWindow::unsendColors(int index)
{
{
const auto &learnSetting = m_ui->tabWidget->learnSetting(index);
emit sendMidi(midi::MidiMessage {
.channel = learnSetting.channel,
.cmd = learnSetting.cmd,
.flag = true,
.note = learnSetting.note,
.velocity = 0
});
}
if (index == 0)
m_ui->drumPadWidget->unsendColors();
else if (index == 1)
@@ -323,6 +338,17 @@ void MainWindow::unsendColors(int index)
void MainWindow::sendColors(int index)
{
{
const auto &learnSetting = m_ui->tabWidget->learnSetting(index);
emit sendMidi(midi::MidiMessage {
.channel = learnSetting.channel,
.cmd = learnSetting.cmd,
.flag = true,
.note = learnSetting.note,
.velocity = 3
});
}
if (index == 0)
m_ui->drumPadWidget->sendColors();
else if (index == 1)

View File

@@ -4,6 +4,7 @@
#include <QtGlobal>
#include "midicontainers.h"
#include "futurecpp.h"
MidiButton::MidiButton(QWidget *parent) :
QPushButton{parent}
@@ -13,6 +14,22 @@ MidiButton::MidiButton(QWidget *parent) :
auto action = new QAction{tr("Learn...")};
connect(action, &QAction::triggered, this, &MidiButton::learn);
addAction(action);
{
m_actionCmd = new QAction{tr("cmd:")};
m_actionCmd->setDisabled(true);
addAction(m_actionCmd);
}
{
m_actionChannel = new QAction{tr("channel:")};
m_actionChannel->setDisabled(true);
addAction(m_actionChannel);
}
{
m_actionNote = new QAction{tr("note:")};
m_actionNote->setDisabled(true);
addAction(m_actionNote);
}
}
MidiButton::MidiButton(const QString &text, QWidget *parent) :
@@ -25,6 +42,16 @@ MidiButton::MidiButton(const QIcon &icon, const QString &text, QWidget *parent)
{
}
void MidiButton::setLearnSetting(const MidiLearnSetting &learnSetting)
{
if (m_learnSetting == learnSetting)
return;
emit learnSettingChanged(m_learnSetting = learnSetting);
m_actionCmd->setText(tr("cmd: %0").arg(std::to_underlying(m_learnSetting.cmd)));
m_actionChannel->setText(tr("channel: %0").arg(m_learnSetting.channel));
m_actionNote->setText(tr("note: %0").arg(m_learnSetting.note));
}
void MidiButton::learn()
{
auto palette = this->palette();
@@ -48,38 +75,49 @@ void MidiButton::learn()
void MidiButton::midiReceived(const midi::MidiMessage &message)
{
if (message.cmd != midi::Command::NoteOn &&
message.cmd != midi::Command::NoteOff &&
message.cmd != midi::Command::ControlChange)
return;
if (m_learning)
{
if ((message.cmd != midi::Command::NoteOn && message.cmd != midi::Command::ControlChange) || message.velocity == 0)
return;
setChannel(message.channel);
setNote(message.note);
setLearnSetting(MidiLearnSetting{
.cmd = message.cmd == midi::Command::NoteOff ? midi::Command::NoteOn : message.cmd,
.channel = message.channel,
.note = message.note
});
learn();
}
else
{
if (message.channel != m_channel || message.note != m_note)
if (message.channel != m_learnSetting.channel ||
message.note != m_learnSetting.note)
return;
switch (message.cmd)
if (m_learnSetting.cmd == midi::Command::NoteOn || m_learnSetting.cmd == midi::Command::NoteOff)
{
switch (message.cmd)
{
case midi::Command::NoteOn:
if (message.velocity != 0)
emit pressed();
else
Q_FALLTHROUGH();
case midi::Command::NoteOff:
emit released();
break;
default:
return;
}
}
else if (m_learnSetting.cmd == message.cmd)
{
case midi::Command::NoteOn:
case midi::Command::ControlChange:
if (message.velocity != 0)
emit pressed();
else
Q_FALLTHROUGH();
case midi::Command::NoteOff:
emit released();
break;
default:
__builtin_unreachable();
emit released();
}
else
return;
}
}

View File

@@ -2,38 +2,39 @@
#include <QPushButton>
#include "midilearnsetting.h"
namespace midi { struct MidiMessage; }
class QAction;
class MidiButton : public QPushButton
{
Q_OBJECT
Q_PROPERTY(quint8 channel READ channel WRITE setChannel NOTIFY channelChanged)
Q_PROPERTY(quint8 note READ note WRITE setNote NOTIFY noteChanged)
Q_PROPERTY(MidiLearnSetting learnSetting READ learnSetting WRITE setLearnSetting NOTIFY learnSettingChanged)
public:
explicit MidiButton(QWidget *parent = nullptr);
explicit MidiButton(const QString &text, QWidget *parent = nullptr);
MidiButton(const QIcon& icon, const QString &text, QWidget *parent = nullptr);
quint8 channel() const { return m_channel; }
void setChannel(quint8 channel) { if (channel == m_channel) return; emit channelChanged(m_channel = channel); }
quint8 note() const { return m_note; }
void setNote(quint8 note) { if (note == m_note) return; emit noteChanged(m_note = note); }
MidiLearnSetting learnSetting() const { return m_learnSetting; }
void setLearnSetting(const MidiLearnSetting &learnSetting);
signals:
void channelChanged(quint8 channel);
void noteChanged(quint8 note);
void learnSettingChanged(const MidiLearnSetting &learnSetting);
public slots:
void learn();
void midiReceived(const midi::MidiMessage &message);
private:
quint8 m_channel{99};
quint8 m_note{99};
MidiLearnSetting m_learnSetting;
bool m_learning{};
QColor m_oldColor;
QBrush m_oldBrush;
QAction *m_actionCmd{};
QAction *m_actionChannel{};
QAction *m_actionNote{};
};

View File

@@ -6,6 +6,7 @@
#include <QDebug>
#include "midicontainers.h"
#include "futurecpp.h"
MidiTabWidget::MidiTabWidget(QWidget *parent) :
QTabWidget{parent}
@@ -14,30 +15,16 @@ MidiTabWidget::MidiTabWidget(QWidget *parent) :
connect(tabBar(), &QWidget::customContextMenuRequested, this, &MidiTabWidget::showContextMenu);
}
quint8 MidiTabWidget::channel(int index) const
MidiLearnSetting MidiTabWidget::learnSetting(int index) const
{
return m_channelNotes[index].channel;
return m_learnSettings[index];
}
void MidiTabWidget::setChannel(int index, quint8 channel)
void MidiTabWidget::setLearnSetting(int index, const MidiLearnSetting &learnSetting)
{
auto &channelNote = m_channelNotes[index];
if (channelNote.channel == channel)
if (learnSetting == m_learnSettings[index])
return;
emit channelChanged(index, channelNote.channel = channel);
}
quint8 MidiTabWidget::note(int index) const
{
return m_channelNotes[index].note;
}
void MidiTabWidget::setNote(int index, quint8 note)
{
auto &channelNote = m_channelNotes[index];
if (channelNote.note == note)
return;
emit noteChanged(index, channelNote.note = note);
emit learnSettingChanged(index, m_learnSettings[index] = learnSetting);
}
void MidiTabWidget::learn(int index)
@@ -67,18 +54,21 @@ void MidiTabWidget::midiReceived(const midi::MidiMessage &message)
if (m_learning)
{
qDebug() << "learning" << message.cmd << message.velocity << message.channel << message.note;
setChannel(*m_learning, message.channel);
setNote(*m_learning, message.note);
setLearnSetting(*m_learning, MidiLearnSetting{
.cmd = message.cmd == midi::Command::NoteOff ? midi::Command::NoteOn : message.cmd,
.channel = message.channel,
.note = message.note
});
learn(*m_learning);
}
else
{
qDebug() << "normal" << message.cmd << message.velocity << message.channel << message.note;
for (int i = 0; i < count(); i++)
{
if (message.channel != m_channelNotes[i].channel ||
message.note != m_channelNotes[i].note)
if (message.cmd != m_learnSettings[i].cmd ||
message.channel != m_learnSettings[i].channel ||
message.note != m_learnSettings[i].note)
continue;
setCurrentIndex(i);
@@ -90,13 +80,13 @@ void MidiTabWidget::midiReceived(const midi::MidiMessage &message)
void MidiTabWidget::tabInserted(int index)
{
QTabWidget::tabInserted(index);
m_channelNotes.insert(std::begin(m_channelNotes) + index, ChannelNote{.channel=quint8(index)});
m_learnSettings.insert(std::begin(m_learnSettings) + index, MidiLearnSetting{});
}
void MidiTabWidget::tabRemoved(int index)
{
QTabWidget::tabInserted(index);
m_channelNotes.erase(std::begin(m_channelNotes) + index);
m_learnSettings.erase(std::begin(m_learnSettings) + index);
}
void MidiTabWidget::showContextMenu(const QPoint &pos)
@@ -107,6 +97,12 @@ void MidiTabWidget::showContextMenu(const QPoint &pos)
QMenu menu{tabBar()};
const auto learnAction = menu.addAction(tr("Learn..."));
{
const auto &learnSetting = m_learnSettings[index];
menu.addAction(tr("cmd: %0").arg(std::to_underlying(learnSetting.cmd)))->setDisabled(true);
menu.addAction(tr("channel: %0").arg(learnSetting.channel))->setDisabled(true);
menu.addAction(tr("note: %0").arg(learnSetting.note))->setDisabled(true);
}
if (const auto selectedAction = menu.exec(tabBar()->mapToGlobal(pos));
selectedAction == learnAction)
{

View File

@@ -5,6 +5,8 @@
#include <optional>
#include <vector>
#include "midilearnsetting.h"
namespace midi { struct MidiMessage; }
class MidiTabWidget : public QTabWidget
@@ -14,15 +16,11 @@ class MidiTabWidget : public QTabWidget
public:
explicit MidiTabWidget(QWidget *parent = nullptr);
quint8 channel(int index) const;
void setChannel(int index, quint8 channel);
quint8 note(int index) const;
void setNote(int index, quint8 note);
MidiLearnSetting learnSetting(int index) const;
void setLearnSetting(int index, const MidiLearnSetting &learnSetting);
signals:
void channelChanged(int index, quint8 channel);
void noteChanged(int index, quint8 note);
void learnSettingChanged(int index, const MidiLearnSetting &learnSetting);
public slots:
void learn(int index);
@@ -39,10 +37,5 @@ private:
std::optional<int> m_learning;
QColor m_oldColor;
struct ChannelNote
{
quint8 channel{99};
quint8 note{99};
};
std::vector<ChannelNote> m_channelNotes;
std::vector<MidiLearnSetting> m_learnSettings;
};

View File

@@ -36,23 +36,15 @@ SequencerWidget::~SequencerWidget() = default;
void SequencerWidget::loadSettings(DrumMachineSettings &settings)
{
m_ui->pushButtonUp->setChannel(settings.drumpadChannelPrevSequence());
m_ui->pushButtonUp->setNote(settings.drumpadNotePrevSequence());
m_ui->pushButtonDown->setChannel(settings.drumpadChannelNextSequence());
m_ui->pushButtonDown->setNote(settings.drumpadNoteNextSequence());
m_ui->pushButtonPlayPause->setChannel(settings.drumpadChannelPlayPause());
m_ui->pushButtonPlayPause->setNote(settings.drumpadNotePlayPause());
m_ui->pushButtonStop->setChannel(settings.drumpadChannelStop());
m_ui->pushButtonStop->setNote(settings.drumpadNoteStop());
m_ui->pushButtonUp->setLearnSetting(settings.drumpadPrevSequence());
m_ui->pushButtonDown->setLearnSetting(settings.drumpadNextSequence());
m_ui->pushButtonPlayPause->setLearnSetting(settings.drumpadPlayPause());
m_ui->pushButtonStop->setLearnSetting(settings.drumpadStop());
connect(m_ui->pushButtonUp, &MidiButton::channelChanged, &settings, &DrumMachineSettings::setDrumpadChannelPrevSequence);
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNotePrevSequence);
connect(m_ui->pushButtonDown, &MidiButton::channelChanged, &settings, &DrumMachineSettings::setDrumpadChannelNextSequence);
connect(m_ui->pushButtonDown, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNoteNextSequence);
connect(m_ui->pushButtonPlayPause, &MidiButton::channelChanged, &settings, &DrumMachineSettings::setDrumpadChannelPlayPause);
connect(m_ui->pushButtonPlayPause, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNotePlayPause);
connect(m_ui->pushButtonStop, &MidiButton::channelChanged, &settings, &DrumMachineSettings::setDrumpadChannelStop);
connect(m_ui->pushButtonStop, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNoteStop);
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);
}
void SequencerWidget::unsendColors()
@@ -60,31 +52,31 @@ void SequencerWidget::unsendColors()
m_sendColors = false;
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->note(),
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->note(),
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = 0
});
}
@@ -94,31 +86,31 @@ void SequencerWidget::sendColors()
m_sendColors = true;
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonUp->learnSetting().channel,
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.note = m_ui->pushButtonUp->learnSetting().note,
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonDown->learnSetting().channel,
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.note = m_ui->pushButtonDown->learnSetting().note,
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonPlayPause->note(),
.note = m_ui->pushButtonPlayPause->learnSetting().note,
.velocity = 60
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->channel(),
.cmd = midi::Command::NoteOn,
.channel = m_ui->pushButtonStop->learnSetting().channel,
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
.flag = true,
.note = m_ui->pushButtonStop->note(),
.note = m_ui->pushButtonStop->learnSetting().note,
.velocity = 3
});
}