Implemented midi control of most buttons in drumpad tab

This commit is contained in:
2022-12-27 20:54:38 +01:00
parent 818f462ae8
commit 626d27653a
30 changed files with 763 additions and 133 deletions

View File

@@ -1,7 +1,6 @@
#include "djwidget.h"
#include "ui_djwidget.h"
#include <QDebug>
#include <QStandardPaths>
DjWidget::DjWidget(QWidget *parent) :
@@ -87,7 +86,7 @@ void DjWidget::sendColors()
{
}
void DjWidget::messageReceived(const midi::MidiMessage &message)
void DjWidget::midiReceived(const midi::MidiMessage &message)
{
}

View File

@@ -31,7 +31,7 @@ signals:
void sendMidi(const midi::MidiMessage &midiMsg);
public slots:
void messageReceived(const midi::MidiMessage &message);
void midiReceived(const midi::MidiMessage &message);
private slots:
void directorySelected();

View File

@@ -6,7 +6,9 @@
#include <QNetworkAccessManager>
#include <QMessageBox>
#include "midicontainers.h"
#include "jsonconverters.h"
#include "drummachinesettings.h"
DrumPadWidget::DrumPadWidget(QWidget *parent) :
QSplitter{parent},
@@ -14,6 +16,10 @@ DrumPadWidget::DrumPadWidget(QWidget *parent) :
{
m_ui->setupUi(this);
connect(m_ui->pushButtonUp, &QAbstractButton::pressed, this, &DrumPadWidget::selectPrevPreset);
connect(m_ui->pushButtonDown, &QAbstractButton::pressed, this, &DrumPadWidget::selectNextPreset);
connect(m_ui->sequencerWidget, &SequencerWidget::sendMidi, this, &DrumPadWidget::sendMidi);
connect(m_ui->samplesWidget, &SamplesWidget::sendMidi, this, &DrumPadWidget::sendMidi);
connect(m_ui->sequencerWidget, &SequencerWidget::triggerSample, m_ui->samplesWidget, &SamplesWidget::sequencerTriggerSample);
@@ -36,19 +42,6 @@ DrumPadWidget::DrumPadWidget(QWidget *parent) :
DrumPadWidget::~DrumPadWidget() = default;
void DrumPadWidget::selectFirstPreset()
{
if (!m_presetsProxyModel.rowCount())
return;
const auto index = m_presetsProxyModel.index(0, 0);
if (index.isValid())
{
m_ui->presetsView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
currentRowChanged(index);
}
}
void DrumPadWidget::writeSamples(frame_t *begin, frame_t *end)
{
m_ui->samplesWidget->writeSamples(begin, end);
@@ -68,22 +61,71 @@ void DrumPadWidget::injectDecodingThread(QThread &thread)
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());
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);
m_ui->sequencerWidget->loadSettings(settings);
m_ui->samplesWidget->loadSettings(settings);
}
void DrumPadWidget::unsendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.velocity = 0
});
m_ui->sequencerWidget->unsendColors();
m_ui->samplesWidget->unsendColors();
}
void DrumPadWidget::sendColors()
{
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.velocity = 127
});
m_ui->sequencerWidget->sendColors();
m_ui->samplesWidget->sendColors();
}
void DrumPadWidget::messageReceived(const midi::MidiMessage &message)
void DrumPadWidget::midiReceived(const midi::MidiMessage &message)
{
m_ui->samplesWidget->messageReceived(message);
m_ui->pushButtonUp->midiReceived(message);
m_ui->pushButtonDown->midiReceived(message);
m_ui->sequencerWidget->midiReceived(message);
m_ui->samplesWidget->midiReceived(message);
}
void DrumPadWidget::currentRowChanged(const QModelIndex &current)
@@ -93,6 +135,11 @@ void DrumPadWidget::currentRowChanged(const QModelIndex &current)
const auto &preset = m_presetsModel.getPreset(m_presetsProxyModel.mapToSource(current));
if (m_settings)
m_settings->setDrumpadLastPresetId(preset.id ? *preset.id : QString{});
else
qWarning() << "no settings available";
m_ui->presetDetailWidget->setPreset(preset);
m_filesModel.setPreset(preset);
m_ui->sequencerWidget->setPreset(preset);
@@ -141,10 +188,83 @@ void DrumPadWidget::requestFinished()
m_presetsModel.setPresets(std::move(*std::move(result).presets));
selectFirstPreset();
if (m_settings)
{
if (const auto &lastPresetId = m_settings->drumpadLastPresetId(); !lastPresetId.isEmpty())
{
if (const auto &index = m_presetsModel.findPresetById(lastPresetId); index.isValid())
selectIndex(m_presetsProxyModel.mapFromSource(index));
else
{
qWarning() << "invalid last preset id" << lastPresetId;
goto noLastId;
}
}
else
goto noLastId;
}
else
{
noLastId:
selectFirstPreset();
}
}
catch (const std::exception &e)
{
QMessageBox::warning(this, tr("error"), tr("error") + "\n\n" + QString::fromStdString(e.what()));
}
}
void DrumPadWidget::selectFirstPreset()
{
if (!m_presetsProxyModel.rowCount())
return;
selectIndex(m_presetsProxyModel.index(0, 0));
}
void DrumPadWidget::selectPrevPreset()
{
if (!m_presetsProxyModel.rowCount())
return;
const auto index = m_ui->presetsView->selectionModel()->currentIndex();
if (!index.isValid())
{
qWarning() << "invalid index";
return;
}
if (index.row() > 0)
selectIndex(m_presetsProxyModel.index(index.row() - 1, 0));
}
void DrumPadWidget::selectNextPreset()
{
if (!m_presetsProxyModel.rowCount())
return;
const auto index = m_ui->presetsView->selectionModel()->currentIndex();
if (!index.isValid())
{
qWarning() << "invalid index";
return;
}
if (index.row() + 1 < m_presetsProxyModel.rowCount())
selectIndex(m_presetsProxyModel.index(index.row() + 1, 0));
}
void DrumPadWidget::selectIndex(const QModelIndex &index)
{
if (!index.isValid())
{
qWarning() << "invalid index";
return;
}
m_ui->presetsView->scrollTo(index);
// m_ui->presetsView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
m_ui->presetsView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
currentRowChanged(index);
}

View File

@@ -6,7 +6,6 @@
#include <memory>
#include "audioformat.h"
#include "midicontainers.h"
#include "presetsmodel.h"
#include "filesmodel.h"
@@ -18,6 +17,7 @@ class QNetworkAccessManager;
class QThread;
class DrumMachineSettings;
class QNetworkReply;
namespace midi { struct MidiMessage; }
class DrumPadWidget : public QSplitter
{
@@ -27,7 +27,6 @@ public:
explicit DrumPadWidget(QWidget *parent = nullptr);
~DrumPadWidget() override;
void selectFirstPreset();
void writeSamples(frame_t *begin, frame_t *end);
void injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager);
void injectDecodingThread(QThread &thread);
@@ -39,16 +38,23 @@ signals:
void sendMidi(const midi::MidiMessage &midiMsg);
public slots:
void messageReceived(const midi::MidiMessage &message);
void midiReceived(const midi::MidiMessage &message);
private slots:
void currentRowChanged(const QModelIndex &current);
void loadPresets();
void requestFinished();
void selectFirstPreset();
void selectPrevPreset();
void selectNextPreset();
private:
void selectIndex(const QModelIndex &index);
const std::unique_ptr<Ui::DrumPadWidget> m_ui;
DrumMachineSettings *m_settings{};
PresetsModel m_presetsModel;
QSortFilterProxyModel m_presetsProxyModel;

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DrumPadWidget</class>
<widget class="QSplitter">
<widget class="QSplitter" name="DrumPadWidget">
<property name="geometry">
<rect>
<x>0</x>
@@ -15,6 +15,9 @@
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout">
<property name="topMargin">
<number>9</number>
</property>
<item>
<layout class="QVBoxLayout">
<item>
@@ -26,6 +29,32 @@
</property>
</widget>
</item>
<item>
<widget class="MidiButton" name="pushButtonUp">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⬆</string>
</property>
</widget>
</item>
<item>
<widget class="MidiButton" name="pushButtonDown">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⬇</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonRefresh">
<property name="maximumSize">
@@ -56,7 +85,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="PresetDetailWidget" name="presetDetailWidget">
<attribute name="title">
@@ -75,12 +104,12 @@
</item>
</layout>
</widget>
<widget class="QSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="SequencerWidget" name="sequencerWidget" />
<widget class="SamplesWidget" name="samplesWidget" />
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="SequencerWidget" name="sequencerWidget" native="true"/>
<widget class="SamplesWidget" name="samplesWidget" native="true"/>
</widget>
</widget>
<customwidgets>
@@ -102,6 +131,11 @@
<header>widgets/sequencerwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>MidiButton</class>
<extends>QPushButton</extends>
<header>widgets/midibutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@@ -9,11 +9,8 @@
#include <QAudioDeviceInfo>
#include <QDebug>
#include "presets.h"
#include "midiinwrapper.h"
#include "midicontainers.h"
#include "sampleswidget.h"
#include "sequencerwidget.h"
namespace {
void DummyDeleter(PaStream *stream);
@@ -42,7 +39,7 @@ MainWindow::MainWindow(QWidget *parent) :
m_ui->drumPadWidget->injectNetworkAccessManager(m_networkAccessManager);
connect(&m_midiIn, &MidiInWrapper::messageReceived, this, &MainWindow::messageReceived);
connect(&m_midiIn, &MidiInWrapper::midiReceived, this, &MainWindow::midiReceived);
{
QEventLoop eventLoop;
@@ -223,18 +220,18 @@ void MainWindow::openMidiOutDevice()
m_ui->pushButtonMidiOut->setText(m_midiOut.isPortOpen() ? tr("Close") : tr("Open"));
}
void MainWindow::messageReceived(const midi::MidiMessage &message)
void MainWindow::midiReceived(const midi::MidiMessage &message)
{
m_ui->statusbar->showMessage(tr("Received midi message: flag: %0 cmd: %1 channel: %2 note: %3 velocity: %4")
.arg(message.flag?"true":"false", QMetaEnum::fromType<midi::Command>().valueToKey(int(message.cmd)))
.arg(message.channel).arg(message.note).arg(message.velocity), 1000);
if (m_ui->tabWidget->currentIndex() == 0)
m_ui->drumPadWidget->messageReceived(message);
m_ui->drumPadWidget->midiReceived(message);
else if (m_ui->tabWidget->currentIndex() == 1)
m_ui->djWidget->messageReceived(message);
m_ui->djWidget->midiReceived(message);
else if (m_ui->tabWidget->currentIndex() == 2)
m_ui->synthisizerWidget->messageReceived(message);
m_ui->synthisizerWidget->midiReceived(message);
}
void MainWindow::sendMidi(const midi::MidiMessage &midiMsg)
@@ -316,7 +313,6 @@ void MainWindow::sendColors(int index)
int k{0};
for (int j = 0; j < 128; j+= 16)
{
qDebug() << k;
for (auto i = 0; i < 8; i++)
{
midi::MidiMessage midiMsg;
@@ -349,6 +345,7 @@ void PaStreamStopperAndCloser(PaStream *stream)
void paStreamFinished(void* userData)
{
Q_UNUSED(userData)
printf("Stream Completed\n");
}

View File

@@ -32,7 +32,7 @@ private slots:
void openAudioDevice();
void openMidiInDevice();
void openMidiOutDevice();
void messageReceived(const midi::MidiMessage &message);
void midiReceived(const midi::MidiMessage &message);
void sendMidi(const midi::MidiMessage &midiMsg);
void currentChanged(int index);

81
widgets/midibutton.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include "midibutton.h"
#include <QAction>
#include "midicontainers.h"
MidiButton::MidiButton(QWidget *parent) :
QPushButton{parent}
{
setContextMenuPolicy(Qt::ActionsContextMenu);
auto action = new QAction{tr("Learn...")};
connect(action, &QAction::triggered, this, &MidiButton::learn);
addAction(action);
}
MidiButton::MidiButton(const QString &text, QWidget *parent) :
QPushButton{text, parent}
{
}
MidiButton::MidiButton(const QIcon &icon, const QString &text, QWidget *parent) :
QPushButton{icon, text, parent}
{
}
void MidiButton::learn()
{
auto palette = this->palette();
if (m_learning)
{
palette.setColor(backgroundRole(), m_oldColor);
palette.setBrush(backgroundRole(), m_oldBrush);
}
else
{
m_oldColor = palette.color(backgroundRole());
m_oldBrush = palette.brush(backgroundRole());
palette.setColor(backgroundRole(), Qt::red);
palette.setBrush(backgroundRole(), Qt::red);
}
setPalette(palette);
m_learning = !m_learning;
}
void MidiButton::midiReceived(const midi::MidiMessage &message)
{
if (message.cmd != midi::Command::NoteOn && message.cmd != midi::Command::NoteOff)
return;
if (m_learning)
{
if (message.cmd != midi::Command::NoteOn)
return;
setChannel(message.channel);
setNote(message.note);
learn();
}
else
{
if (message.channel != m_channel || message.note != m_note)
return;
switch (message.cmd)
{
case midi::Command::NoteOn:
if (message.velocity == 0)
emit released();
else
emit pressed();
return;
case midi::Command::NoteOff:
emit released();
return;
default: __builtin_unreachable();
}
}
}

39
widgets/midibutton.h Normal file
View File

@@ -0,0 +1,39 @@
#pragma once
#include <QPushButton>
namespace midi { struct MidiMessage; }
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)
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); }
signals:
void channelChanged(quint8 channel);
void noteChanged(quint8 note);
public slots:
void learn();
void midiReceived(const midi::MidiMessage &message);
private:
quint8 m_channel{99};
quint8 m_note{99};
bool m_learning{};
QColor m_oldColor;
QBrush m_oldBrush;
};

View File

@@ -41,7 +41,7 @@ void SamplesWidget::setPreset(const presets::Preset &preset)
updateWidgets();
}
void SamplesWidget::messageReceived(const midi::MidiMessage &message)
void SamplesWidget::midiReceived(const midi::MidiMessage &message)
{
if (message == midi::MidiMessage{.channel=0,.cmd=midi::Command::ControlChange,.flag=true,.note=64,.velocity=127})
{

View File

@@ -10,7 +10,7 @@
#include "presets.h"
namespace Ui { class SamplesWidget; }
namespace midi { class MidiMessage; }
namespace midi { struct MidiMessage; }
class QNetworkAccessManager;
class SampleWidget;
class DrumMachineSettings;
@@ -27,7 +27,7 @@ public:
void setPreset(const presets::Preset &preset);
void messageReceived(const midi::MidiMessage &message);
void midiReceived(const midi::MidiMessage &message);
void writeSamples(frame_t *begin, frame_t *end);

View File

@@ -7,7 +7,6 @@
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QMetaEnum>
#include <QDebug>
#include "audiodecoder.h"
#include "drummachinesettings.h"
@@ -41,8 +40,8 @@ SampleWidget::~SampleWidget() = default;
void SampleWidget::loadSettings(DrumMachineSettings &settings)
{
m_ui->channelSpinBox->setValue(settings.padChannel(m_padNr));
m_ui->noteSpinBox->setValue(settings.padNote(m_padNr));
m_ui->channelSpinBox->setValue(settings.drumpadChannel(m_padNr));
m_ui->noteSpinBox->setValue(settings.drumpadNote(m_padNr));
m_settings = &settings;
}
@@ -90,7 +89,9 @@ void SampleWidget::setChannel(quint8 channel)
m_ui->channelSpinBox->setValue(channel);
if (m_settings)
m_settings->setPadChannel(m_padNr, channel);
m_settings->setDrumpadChannel(m_padNr, channel);
else
qWarning() << "no settings available";
}
quint8 SampleWidget::note() const
@@ -103,7 +104,9 @@ void SampleWidget::setNote(quint8 note)
m_ui->noteSpinBox->setValue(note);
if (m_settings)
m_settings->setPadNote(m_padNr, note);
m_settings->setDrumpadNote(m_padNr, note);
else
qWarning() << "no settings available";
}
int SampleWidget::speed() const
@@ -322,7 +325,6 @@ void SampleWidget::learnPressed()
m_ui->toolButtonLearn->setPalette(palette);
m_learning = !m_learning;
qDebug() << m_learning;
}
void SampleWidget::startRequest()

View File

@@ -7,7 +7,6 @@
#include "audioformat.h"
#include "presets.h"
#include "audioplayer.h"
#include "midicontainers.h"
namespace Ui { class SampleWidget; }
class QNetworkAccessManager;
@@ -15,6 +14,7 @@ class QNetworkReply;
class QAudioBuffer;
class AudioDecoder;
class DrumMachineSettings;
namespace midi { struct MidiMessage; }
class SampleWidget : public QFrame
{

View File

@@ -62,7 +62,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="pushButton">
<widget class="MidiButton" name="pushButton">
<property name="maximumSize">
<size>
<width>32</width>
@@ -151,6 +151,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MidiButton</class>
<extends>QPushButton</extends>
<header>widgets/midibutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -6,6 +6,8 @@
#include <QDebug>
#include "presets.h"
#include "drummachinesettings.h"
#include "midicontainers.h"
SequencerWidget::SequencerWidget(QWidget *parent) :
QWidget{parent},
@@ -14,12 +16,17 @@ SequencerWidget::SequencerWidget(QWidget *parent) :
m_ui->setupUi(this);
connect(m_ui->spinBoxTempo, qOverload<int>(&QSpinBox::valueChanged), this, &SequencerWidget::tempoChanged);
connect(m_ui->comboBoxSequence, qOverload<int>(&QComboBox::currentIndexChanged), this, &SequencerWidget::sequenceSelected);
connect(m_ui->horizontalSlider, &QSlider::valueChanged, this, [=](int value){ m_pos = value; updateStatusLabel(); });
connect(m_ui->comboBoxSequence, qOverload<int>(&QComboBox::currentIndexChanged), this, &SequencerWidget::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->horizontalSlider, &QSlider::valueChanged, this, [=](int value){ m_pos = value; updateStatusLabel(); });
connect(&m_timer, &QTimer::timeout, this, &SequencerWidget::timeout);
updateStatusLabel();
@@ -27,6 +34,95 @@ SequencerWidget::SequencerWidget(QWidget *parent) :
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());
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);
}
void SequencerWidget::unsendColors()
{
m_sendColors = false;
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonPlayPause->note(),
.velocity = 0
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonStop->note(),
.velocity = 0
});
}
void SequencerWidget::sendColors()
{
m_sendColors = true;
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonUp->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonUp->note(),
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonDown->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonDown->note(),
.velocity = 127
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonPlayPause->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonPlayPause->note(),
.velocity = 60
});
emit sendMidi(midi::MidiMessage {
.channel = m_ui->pushButtonStop->channel(),
.cmd = midi::Command::NoteOn,
.flag = true,
.note = m_ui->pushButtonStop->note(),
.velocity = 3
});
}
void SequencerWidget::setPreset(const presets::Preset &preset)
{
if (preset.tempo)
@@ -66,6 +162,14 @@ void SequencerWidget::setPreset(const presets::Preset &preset)
sequenceSelected();
}
void SequencerWidget::midiReceived(const midi::MidiMessage &message)
{
m_ui->pushButtonUp->midiReceived(message);
m_ui->pushButtonDown->midiReceived(message);
m_ui->pushButtonPlayPause->midiReceived(message);
m_ui->pushButtonStop->midiReceived(message);
}
void SequencerWidget::playPause()
{
if (m_timer.isActive())
@@ -151,3 +255,15 @@ void SequencerWidget::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()
{
if (const auto index = m_ui->comboBoxSequence->currentIndex(); index > 0)
m_ui->comboBoxSequence->setCurrentIndex(index - 1);
}
void SequencerWidget::selectNextSequence()
{
if (const auto index = m_ui->comboBoxSequence->currentIndex(); index + 1 < m_ui->comboBoxSequence->count())
m_ui->comboBoxSequence->setCurrentIndex(index + 1);
}

View File

@@ -7,9 +7,11 @@
#include <QWidget>
#include <QTimer>
class QLabel;
namespace Ui { class SequencerWidget; }
namespace presets { class Preset; class Sequence; }
class QLabel;
class DrumMachineSettings;
namespace midi { struct MidiMessage; }
class SequencerWidget : public QWidget
{
@@ -19,11 +21,19 @@ public:
explicit SequencerWidget(QWidget *parent = nullptr);
~SequencerWidget() override;
void loadSettings(DrumMachineSettings &settings);
void unsendColors();
void sendColors();
void setPreset(const presets::Preset &preset);
signals:
void sendMidi(const midi::MidiMessage &midiMsg);
void triggerSample(int index);
public slots:
void midiReceived(const midi::MidiMessage &message);
private slots:
void playPause();
void stop();
@@ -34,6 +44,9 @@ private slots:
void updateStatusLabel();
void selectPrevSequence();
void selectNextSequence();
private:
const std::unique_ptr<Ui::SequencerWidget> m_ui;
@@ -44,4 +57,6 @@ private:
int m_pos{};
std::array<QLabel*, 24> m_sampleLabels;
bool m_sendColors{};
};

View File

@@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,1">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,0,0,1">
<item>
<widget class="QSpinBox" name="spinBoxTempo">
<property name="suffix">
@@ -30,7 +30,33 @@
<widget class="QComboBox" name="comboBoxSequence"/>
</item>
<item>
<widget class="QPushButton" name="pushButtonPlayPause">
<widget class="MidiButton" name="pushButtonUp">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⬆</string>
</property>
</widget>
</item>
<item>
<widget class="MidiButton" name="pushButtonDown">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>⬇</string>
</property>
</widget>
</item>
<item>
<widget class="MidiButton" name="pushButtonPlayPause">
<property name="maximumSize">
<size>
<width>32</width>
@@ -43,7 +69,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonStop">
<widget class="MidiButton" name="pushButtonStop">
<property name="maximumSize">
<size>
<width>32</width>
@@ -82,26 +108,26 @@
<x>0</x>
<y>0</y>
<width>878</width>
<height>921</height>
<height>828</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,1">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,1,0">
<item row="38" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample18">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="34" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample16">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="19" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -111,14 +137,14 @@
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample4">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -128,14 +154,14 @@
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample6">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -145,7 +171,7 @@
</widget>
</item>
<item row="15" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -155,7 +181,7 @@
</widget>
</item>
<item row="41" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -165,14 +191,14 @@
</widget>
</item>
<item row="44" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample21">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="47" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -182,7 +208,7 @@
</widget>
</item>
<item row="29" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -192,21 +218,21 @@
</widget>
</item>
<item row="32" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample15">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample5">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="27" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -216,14 +242,14 @@
</widget>
</item>
<item row="48" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample23">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -233,28 +259,28 @@
</widget>
</item>
<item row="28" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample13">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample8">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample7">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -264,7 +290,7 @@
</widget>
</item>
<item row="25" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -274,35 +300,35 @@
</widget>
</item>
<item row="40" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample19">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="30" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample14">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="26" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample12">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="43" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -312,14 +338,14 @@
</widget>
</item>
<item row="42" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample20">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -329,7 +355,7 @@
</widget>
</item>
<item row="39" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -339,7 +365,7 @@
</widget>
</item>
<item row="21" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -349,7 +375,7 @@
</widget>
</item>
<item row="31" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -359,7 +385,7 @@
</widget>
</item>
<item row="23" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -369,7 +395,7 @@
</widget>
</item>
<item row="37" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -379,14 +405,14 @@
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample1">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="35" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -396,7 +422,7 @@
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -406,14 +432,14 @@
</widget>
</item>
<item row="20" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample9">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="17" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -423,14 +449,14 @@
</widget>
</item>
<item row="36" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample17">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="49" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::VLine</enum>
</property>
@@ -440,21 +466,21 @@
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample3">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample0">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="33" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -464,14 +490,14 @@
</widget>
</item>
<item row="22" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample10">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -481,14 +507,14 @@
</widget>
</item>
<item row="46" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample22">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="45" column="0" colspan="3">
<widget class="QFrame">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
@@ -498,14 +524,14 @@
</widget>
</item>
<item row="24" column="0">
<widget class="QLabel">
<widget class="QLabel" name="labelSample11">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel">
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
@@ -517,6 +543,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MidiButton</class>
<extends>QPushButton</extends>
<header>widgets/midibutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -24,6 +24,7 @@ void SynthisizerWidget::writeSamples(frame_t *begin, frame_t *end)
void SynthisizerWidget::loadSettings(DrumMachineSettings &settings)
{
Q_UNUSED(settings)
}
void SynthisizerWidget::unsendColors()
@@ -34,7 +35,7 @@ void SynthisizerWidget::sendColors()
{
}
void SynthisizerWidget::messageReceived(const midi::MidiMessage &message)
void SynthisizerWidget::midiReceived(const midi::MidiMessage &message)
{
if (message.cmd == midi::Command::NoteOff || (message.cmd == midi::Command::NoteOn && message.velocity == 0))
{

View File

@@ -8,6 +8,7 @@
namespace Ui { class SynthisizerWidget; }
class DrumMachineSettings;
namespace midi { struct MidiMessage; }
class SynthisizerWidget : public QWidget
{
@@ -26,7 +27,7 @@ signals:
void sendMidi(const midi::MidiMessage &midiMsg);
public slots:
void messageReceived(const midi::MidiMessage &message);
void midiReceived(const midi::MidiMessage &message);
private:
const std::unique_ptr<Ui::SynthisizerWidget> m_ui;

View File

@@ -10,7 +10,6 @@
#include <QUrl>
#include <QFileInfo>
#include <QButtonGroup>
#include <QDebug>
#include "audiodecoder.h"