Fixed midi handling for control change and implemented tab selection with midi
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
QT = core multimedia gui widgets network
|
QT = core multimedia gui widgets network
|
||||||
|
|
||||||
CONFIG += c++20
|
CONFIG += c++22
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -Werror=all
|
QMAKE_CXXFLAGS += -Werror=all
|
||||||
release: QMAKE_CXXFLAGS_RELEASE -= -O1
|
release: QMAKE_CXXFLAGS_RELEASE -= -O1
|
||||||
@ -30,6 +30,7 @@ SOURCES += \
|
|||||||
main.cpp \
|
main.cpp \
|
||||||
midicontainers.cpp \
|
midicontainers.cpp \
|
||||||
midiinwrapper.cpp \
|
midiinwrapper.cpp \
|
||||||
|
midilearnsetting.cpp \
|
||||||
midioutwrapper.cpp \
|
midioutwrapper.cpp \
|
||||||
synthisizer.cpp \
|
synthisizer.cpp \
|
||||||
treetotableproxymodel.cpp \
|
treetotableproxymodel.cpp \
|
||||||
@ -60,6 +61,7 @@ HEADERS += \
|
|||||||
drumpadpresets.h \
|
drumpadpresets.h \
|
||||||
drumpadpresetsmodel.h \
|
drumpadpresetsmodel.h \
|
||||||
drumpadpresettagsmodel.h \
|
drumpadpresettagsmodel.h \
|
||||||
|
futurecpp.h \
|
||||||
graphrenderer.h \
|
graphrenderer.h \
|
||||||
jsonconverters.h \
|
jsonconverters.h \
|
||||||
loopstationjsonconverters.h \
|
loopstationjsonconverters.h \
|
||||||
@ -68,6 +70,7 @@ HEADERS += \
|
|||||||
loopstationpresettagsmodel.h \
|
loopstationpresettagsmodel.h \
|
||||||
midicontainers.h \
|
midicontainers.h \
|
||||||
midiinwrapper.h \
|
midiinwrapper.h \
|
||||||
|
midilearnsetting.h \
|
||||||
midioutwrapper.h \
|
midioutwrapper.h \
|
||||||
synthisizer.h \
|
synthisizer.h \
|
||||||
treetotableproxymodel.h \
|
treetotableproxymodel.h \
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "midilearnsetting.h"
|
||||||
|
#include "futurecpp.h"
|
||||||
|
|
||||||
QString DrumMachineSettings::defaultCacheDir() const
|
QString DrumMachineSettings::defaultCacheDir() const
|
||||||
{
|
{
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
return QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
||||||
@ -73,6 +76,16 @@ void DrumMachineSettings::setLastMidiOutDevice(const QString &lastMidiOutDevice)
|
|||||||
setValue("lastMidiOutDevice", lastMidiOutDevice);
|
setValue("lastMidiOutDevice", lastMidiOutDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MidiLearnSetting DrumMachineSettings::tabWidget(quint8 index) const
|
||||||
|
{
|
||||||
|
return learnSetting(QString{"tabWidget%0"}.arg(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumMachineSettings::setTabWidget(quint8 index, const MidiLearnSetting &value)
|
||||||
|
{
|
||||||
|
setLearnSetting(QString{"tabWidget%0"}.arg(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
QString DrumMachineSettings::drumpadLastPresetId() const
|
QString DrumMachineSettings::drumpadLastPresetId() const
|
||||||
{
|
{
|
||||||
return value("drumpad/lastPresetId").toString();
|
return value("drumpad/lastPresetId").toString();
|
||||||
@ -83,144 +96,74 @@ void DrumMachineSettings::setDrumpadLastPresetId(const QString &lastPresetId)
|
|||||||
setValue("drumpad/lastPresetId", lastPresetId);
|
setValue("drumpad/lastPresetId", lastPresetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelPrevPreset() const
|
MidiLearnSetting DrumMachineSettings::drumpadPrevPreset() const
|
||||||
{
|
{
|
||||||
return value("drumpad/prevPreset_channel", 99).toUInt();
|
return learnSetting("drumpad/prevPreset");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelPrevPreset(quint8 channel)
|
void DrumMachineSettings::setDrumpadPrevPreset(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/prevPreset_channel", channel);
|
setLearnSetting("drumpad/prevPreset", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNotePrevPreset() const
|
MidiLearnSetting DrumMachineSettings::drumpadNextPreset() const
|
||||||
{
|
{
|
||||||
return value("drumpad/prevPreset_note", 99).toUInt();
|
return learnSetting("drumpad/nextPreset");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNotePrevPreset(quint8 note)
|
void DrumMachineSettings::setDrumpadNextPreset(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/prevPreset_note", note);
|
setLearnSetting("drumpad/nextPreset", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelNextPreset() const
|
MidiLearnSetting DrumMachineSettings::drumpadPrevSequence() const
|
||||||
{
|
{
|
||||||
return value("drumpad/nextPreset_channel", 99).toUInt();
|
return learnSetting("drumpad/prevSequence");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelNextPreset(quint8 channel)
|
void DrumMachineSettings::setDrumpadPrevSequence(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/nextPreset_channel", channel);
|
setLearnSetting("drumpad/prevSequence", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNoteNextPreset() const
|
MidiLearnSetting DrumMachineSettings::drumpadNextSequence() const
|
||||||
{
|
{
|
||||||
return value("drumpad/nextPreset_note", 99).toUInt();
|
return learnSetting("drumpad/nextSequence");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNoteNextPreset(quint8 note)
|
void DrumMachineSettings::setDrumpadNextSequence(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/nextPreset_note", note);
|
setLearnSetting("drumpad/nextSequence", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelPrevSequence() const
|
MidiLearnSetting DrumMachineSettings::drumpadPlayPause() const
|
||||||
{
|
{
|
||||||
return value("drumpad/prevSequence_channel", 99).toUInt();
|
return learnSetting("drumpad/playPause");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelPrevSequence(quint8 channel)
|
void DrumMachineSettings::setDrumpadPlayPause(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/prevSequence_channel", channel);
|
setLearnSetting("drumpad/playPause", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNotePrevSequence() const
|
MidiLearnSetting DrumMachineSettings::drumpadStop() const
|
||||||
{
|
{
|
||||||
return value("drumpad/prevSequence_note", 99).toUInt();
|
return learnSetting("drumpad/stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNotePrevSequence(quint8 note)
|
void DrumMachineSettings::setDrumpadStop(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/prevSequence_note", note);
|
setLearnSetting("drumpad/stop", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelNextSequence() const
|
MidiLearnSetting DrumMachineSettings::drumpadSample(quint8 pad) const
|
||||||
{
|
{
|
||||||
return value("drumpad/nextSequence_channel", 99).toUInt();
|
return learnSetting(QString{"drumpad/pad%0"}.arg(pad));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelNextSequence(quint8 channel)
|
void DrumMachineSettings::setDrumpadSample(quint8 pad, const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("drumpad/nextSequence_channel", channel);
|
setLearnSetting(QString{"drumpad/pad%0"}.arg(pad), value);
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNoteNextSequence() const
|
|
||||||
{
|
|
||||||
return value("drumpad/nextSequence_note", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNoteNextSequence(quint8 note)
|
|
||||||
{
|
|
||||||
setValue("drumpad/nextSequence_note", note);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelPlayPause() const
|
|
||||||
{
|
|
||||||
return value("drumpad/playPause_channel", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelPlayPause(quint8 channel)
|
|
||||||
{
|
|
||||||
setValue("drumpad/playPause_channel", channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNotePlayPause() const
|
|
||||||
{
|
|
||||||
return value("drumpad/playPause_note", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNotePlayPause(quint8 note)
|
|
||||||
{
|
|
||||||
setValue("drumpad/playPause_note", note);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannelStop() const
|
|
||||||
{
|
|
||||||
return value("drumpad/stop_channel", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannelStop(quint8 channel)
|
|
||||||
{
|
|
||||||
setValue("drumpad/stop_channel", channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNoteStop() const
|
|
||||||
{
|
|
||||||
return value("drumpad/stop_note", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNoteStop(quint8 note)
|
|
||||||
{
|
|
||||||
setValue("drumpad/stop_note", note);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadChannel(quint8 pad) const
|
|
||||||
{
|
|
||||||
return value(QString{"drumpad/pad%0_channel"}.arg(pad), 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadChannel(quint8 pad, quint8 channel)
|
|
||||||
{
|
|
||||||
setValue(QString{"drumpad/pad%0_channel"}.arg(pad), channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint8 DrumMachineSettings::drumpadNote(quint8 pad) const
|
|
||||||
{
|
|
||||||
return value(QString{"drumpad/pad%0_note"}.arg(pad), 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setDrumpadNote(quint8 pad, quint8 note)
|
|
||||||
{
|
|
||||||
setValue(QString{"drumpad/pad%0_note"}.arg(pad), note);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DrumMachineSettings::loopstationLastPresetId() const
|
QString DrumMachineSettings::loopstationLastPresetId() const
|
||||||
@ -233,42 +176,38 @@ void DrumMachineSettings::setLoopstationLastPresetId(const QString &lastPresetId
|
|||||||
setValue("loopstation/lastPresetId", lastPresetId);
|
setValue("loopstation/lastPresetId", lastPresetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::loopstationChannelPrevPreset() const
|
MidiLearnSetting DrumMachineSettings::loopstationPrevPreset() const
|
||||||
{
|
{
|
||||||
return value("loopstation/prevPreset_channel", 99).toUInt();
|
return learnSetting("loopstation/prevPreset");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setLoopstationChannelPrevPreset(quint8 channel)
|
void DrumMachineSettings::setLoopstationPrevPreset(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("loopstation/prevPreset_channel", channel);
|
setLearnSetting("loopstation/prevPreset", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::loopstationNotePrevPreset() const
|
MidiLearnSetting DrumMachineSettings::loopstationNextPreset() const
|
||||||
{
|
{
|
||||||
return value("loopstation/prevPreset_note", 99).toUInt();
|
return learnSetting("loopstation/nextPreset");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setLoopstationNotePrevPreset(quint8 note)
|
void DrumMachineSettings::setLoopstationNextPreset(const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("loopstation/prevPreset_note", note);
|
setLearnSetting("loopstation/nextPreset", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 DrumMachineSettings::loopstationChannelNextPreset() const
|
MidiLearnSetting DrumMachineSettings::learnSetting(const QString &key) const
|
||||||
{
|
{
|
||||||
return value("loopstation/nextPreset_channel", 99).toUInt();
|
return MidiLearnSetting{
|
||||||
|
.cmd = midi::Command(value(QString{"%0_cmd"}.arg(key), std::to_underlying(midi::Command::NoteOn)).value<std::underlying_type_t<midi::Command>>()),
|
||||||
|
.channel = value(QString{"%0_channel"}.arg(key), 99).value<quint8>(),
|
||||||
|
.note = value(QString{"%0_note"}.arg(key), 99).value<quint8>()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumMachineSettings::setLoopstationChannelNextPreset(quint8 channel)
|
void DrumMachineSettings::setLearnSetting(const QString &key, const MidiLearnSetting &value)
|
||||||
{
|
{
|
||||||
setValue("loopstation/nextPreset_channel", channel);
|
setValue(QString{"%0_note"}.arg(key), std::to_underlying(value.cmd));
|
||||||
}
|
setValue(QString{"%0_channel"}.arg(key), value.channel);
|
||||||
|
setValue(QString{"%0_note"}.arg(key), value.note);
|
||||||
quint8 DrumMachineSettings::loopstationNoteNextPreset() const
|
|
||||||
{
|
|
||||||
return value("loopstation/nextPreset_note", 99).toUInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrumMachineSettings::setLoopstationNoteNextPreset(quint8 note)
|
|
||||||
{
|
|
||||||
setValue("loopstation/nextPreset_note", note);
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
|
struct MidiLearnSetting;
|
||||||
|
|
||||||
class DrumMachineSettings : public QSettings
|
class DrumMachineSettings : public QSettings
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -27,58 +29,47 @@ public:
|
|||||||
QString lastMidiOutDevice() const;
|
QString lastMidiOutDevice() const;
|
||||||
void setLastMidiOutDevice(const QString &lastMidiOutDevice);
|
void setLastMidiOutDevice(const QString &lastMidiOutDevice);
|
||||||
|
|
||||||
|
MidiLearnSetting tabWidget(quint8 index) const;
|
||||||
|
void setTabWidget(quint8 index, const MidiLearnSetting &value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QString drumpadLastPresetId() const;
|
QString drumpadLastPresetId() const;
|
||||||
void setDrumpadLastPresetId(const QString &lastPresetId);
|
void setDrumpadLastPresetId(const QString &lastPresetId);
|
||||||
|
|
||||||
quint8 drumpadChannelPrevPreset() const;
|
MidiLearnSetting drumpadPrevPreset() const;
|
||||||
void setDrumpadChannelPrevPreset(quint8 channel);
|
void setDrumpadPrevPreset(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNotePrevPreset() const;
|
|
||||||
void setDrumpadNotePrevPreset(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannelNextPreset() const;
|
MidiLearnSetting drumpadNextPreset() const;
|
||||||
void setDrumpadChannelNextPreset(quint8 channel);
|
void setDrumpadNextPreset(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNoteNextPreset() const;
|
|
||||||
void setDrumpadNoteNextPreset(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannelPrevSequence() const;
|
MidiLearnSetting drumpadPrevSequence() const;
|
||||||
void setDrumpadChannelPrevSequence(quint8 channel);
|
void setDrumpadPrevSequence(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNotePrevSequence() const;
|
|
||||||
void setDrumpadNotePrevSequence(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannelNextSequence() const;
|
MidiLearnSetting drumpadNextSequence() const;
|
||||||
void setDrumpadChannelNextSequence(quint8 channel);
|
void setDrumpadNextSequence(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNoteNextSequence() const;
|
|
||||||
void setDrumpadNoteNextSequence(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannelPlayPause() const;
|
MidiLearnSetting drumpadPlayPause() const;
|
||||||
void setDrumpadChannelPlayPause(quint8 channel);
|
void setDrumpadPlayPause(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNotePlayPause() const;
|
|
||||||
void setDrumpadNotePlayPause(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannelStop() const;
|
MidiLearnSetting drumpadStop() const;
|
||||||
void setDrumpadChannelStop(quint8 channel);
|
void setDrumpadStop(const MidiLearnSetting &value);
|
||||||
quint8 drumpadNoteStop() const;
|
|
||||||
void setDrumpadNoteStop(quint8 note);
|
|
||||||
|
|
||||||
quint8 drumpadChannel(quint8 pad) const;
|
MidiLearnSetting drumpadSample(quint8 pad) const;
|
||||||
void setDrumpadChannel(quint8 pad, quint8 channel);
|
void setDrumpadSample(quint8 pad, const MidiLearnSetting &value);
|
||||||
quint8 drumpadNote(quint8 pad) const;
|
|
||||||
void setDrumpadNote(quint8 pad, quint8 note);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QString loopstationLastPresetId() const;
|
QString loopstationLastPresetId() const;
|
||||||
void setLoopstationLastPresetId(const QString &lastPresetId);
|
void setLoopstationLastPresetId(const QString &lastPresetId);
|
||||||
|
|
||||||
quint8 loopstationChannelPrevPreset() const;
|
MidiLearnSetting loopstationPrevPreset() const;
|
||||||
void setLoopstationChannelPrevPreset(quint8 channel);
|
void setLoopstationPrevPreset(const MidiLearnSetting &value);
|
||||||
quint8 loopstationNotePrevPreset() const;
|
|
||||||
void setLoopstationNotePrevPreset(quint8 note);
|
|
||||||
|
|
||||||
quint8 loopstationChannelNextPreset() const;
|
MidiLearnSetting loopstationNextPreset() const;
|
||||||
void setLoopstationChannelNextPreset(quint8 channel);
|
void setLoopstationNextPreset(const MidiLearnSetting &value);
|
||||||
quint8 loopstationNoteNextPreset() const;
|
|
||||||
void setLoopstationNoteNextPreset(quint8 note);
|
private:
|
||||||
|
MidiLearnSetting learnSetting(const QString &key) const;
|
||||||
|
void setLearnSetting(const QString &key, const MidiLearnSetting &value);
|
||||||
};
|
};
|
||||||
|
30
futurecpp.h
Normal file
30
futurecpp.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// system includes
|
||||||
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// C++20 backports (until espressif finally updates their aged compiler suite)
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <class To, class From>
|
||||||
|
typename std::enable_if_t<
|
||||||
|
sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && std::is_trivially_copyable_v<To>,
|
||||||
|
To>
|
||||||
|
// constexpr support needs compiler magic
|
||||||
|
bit_cast(const From& src) noexcept
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_constructible_v<To>,
|
||||||
|
"This implementation additionally requires destination type to be trivially constructible");
|
||||||
|
|
||||||
|
To dst;
|
||||||
|
std::memcpy(&dst, &src, sizeof(To));
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>>
|
||||||
|
constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept {
|
||||||
|
return static_cast<std::underlying_type_t<EnumT>>(e);
|
||||||
|
}
|
||||||
|
} // namespace std
|
@ -1,6 +1,10 @@
|
|||||||
#include "midicontainers.h"
|
#include "midicontainers.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QDebugStateSaver>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
#include "futurecpp.h"
|
||||||
|
|
||||||
namespace midi {
|
namespace midi {
|
||||||
bool MidiMessage::operator==(const MidiMessage &other) const
|
bool MidiMessage::operator==(const MidiMessage &other) const
|
||||||
@ -11,13 +15,64 @@ bool MidiMessage::operator==(const MidiMessage &other) const
|
|||||||
note == other.note &&
|
note == other.note &&
|
||||||
velocity == other.velocity;
|
velocity == other.velocity;
|
||||||
}
|
}
|
||||||
}
|
} // namespace midi
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void registerMidiMessageMetatype()
|
void registerMidiMessageMetatype()
|
||||||
{
|
{
|
||||||
|
qRegisterMetaType<midi::Command>();
|
||||||
qRegisterMetaType<midi::MidiMessage>();
|
qRegisterMetaType<midi::MidiMessage>();
|
||||||
|
|
||||||
|
qRegisterMetaTypeStreamOperators<midi::Command>("midi::Command");
|
||||||
|
qRegisterMetaTypeStreamOperators<midi::MidiMessage>("midi::MidiMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_COREAPP_STARTUP_FUNCTION(registerMidiMessageMetatype)
|
Q_COREAPP_STARTUP_FUNCTION(registerMidiMessageMetatype)
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const midi::MidiMessage &value)
|
||||||
|
{
|
||||||
|
QDebugStateSaver saver{debug};
|
||||||
|
debug.nospace() << "midi::MidiMessage{.channel=" << value.channel << ",.cmd=" << value.cmd << ",.flag=" << value.flag << ",.note=" << value.note << ",.velocity=" << value.velocity << "}";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const midi::Command &value)
|
||||||
|
{
|
||||||
|
return out << std::to_underlying(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &in, midi::Command &value)
|
||||||
|
{
|
||||||
|
std::underlying_type_t<midi::Command> v;
|
||||||
|
in >> v;
|
||||||
|
value = midi::Command(v);
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const midi::MidiMessage &value)
|
||||||
|
{
|
||||||
|
return out << value.channel << value.cmd << value.flag << value.note << value.velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &in, midi::MidiMessage &value)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typeof(value.channel) channel;
|
||||||
|
in >> channel;
|
||||||
|
value.channel = channel;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typeof(value.cmd) cmd;
|
||||||
|
in >> cmd;
|
||||||
|
value.cmd = cmd;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typeof(value.flag) flag;
|
||||||
|
in >> flag;
|
||||||
|
value.flag = flag;
|
||||||
|
}
|
||||||
|
in >> value.note;
|
||||||
|
in >> value.velocity;
|
||||||
|
return in;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,16 @@ struct MidiMessage
|
|||||||
|
|
||||||
bool operator==(const MidiMessage &other) const;
|
bool operator==(const MidiMessage &other) const;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
} // namespace midi
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(midi::Command)
|
||||||
Q_DECLARE_METATYPE(midi::MidiMessage)
|
Q_DECLARE_METATYPE(midi::MidiMessage)
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const midi::MidiMessage &value);
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const midi::Command &value);
|
||||||
|
QDataStream &operator>>(QDataStream &in, midi::Command &value);
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const midi::MidiMessage &value);
|
||||||
|
QDataStream &operator>>(QDataStream &in, midi::MidiMessage &value);
|
||||||
|
42
midilearnsetting.cpp
Normal file
42
midilearnsetting.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "midilearnsetting.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebugStateSaver>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void registerMidiLearnMessageMetatype()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<MidiLearnSetting>();
|
||||||
|
|
||||||
|
qRegisterMetaTypeStreamOperators<MidiLearnSetting>("MidiLearnSetting");
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_COREAPP_STARTUP_FUNCTION(registerMidiLearnMessageMetatype)
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool MidiLearnSetting::operator==(const MidiLearnSetting &other) const
|
||||||
|
{
|
||||||
|
return cmd == other.cmd &&
|
||||||
|
channel == other.channel &&
|
||||||
|
note == other.note;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const MidiLearnSetting &value)
|
||||||
|
{
|
||||||
|
QDebugStateSaver saver{debug};
|
||||||
|
debug.nospace() << "MidiLearnSetting{.cmd=" << value.cmd << ",.channel=" << value.channel << ",.note=" << value.note << "}";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const MidiLearnSetting &value)
|
||||||
|
{
|
||||||
|
out << value.cmd << value.channel << value.note;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &in, MidiLearnSetting &value)
|
||||||
|
{
|
||||||
|
in >> value.cmd >> value.channel >> value.note;
|
||||||
|
return in;
|
||||||
|
}
|
23
midilearnsetting.h
Normal file
23
midilearnsetting.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
|
#include "midicontainers.h"
|
||||||
|
|
||||||
|
struct MidiLearnSetting
|
||||||
|
{
|
||||||
|
midi::Command cmd{midi::Command::NoteOn};
|
||||||
|
quint8 channel{99};
|
||||||
|
quint8 note{99};
|
||||||
|
|
||||||
|
bool operator==(const MidiLearnSetting &other) const;
|
||||||
|
QDebug operator<<(QDebug debug) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(MidiLearnSetting);
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const MidiLearnSetting &value);
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &out, const MidiLearnSetting &value);
|
||||||
|
QDataStream &operator>>(QDataStream &in, MidiLearnSetting &value);
|
@ -51,34 +51,9 @@ void DrumPadSamplesWidget::midiReceived(const midi::MidiMessage &message)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.cmd != midi::Command::NoteOn &&
|
|
||||||
message.cmd != midi::Command::NoteOff &&
|
|
||||||
message.cmd != midi::Command::ControlChange)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (DrumPadSampleWidget &widget : getWidgets())
|
for (DrumPadSampleWidget &widget : getWidgets())
|
||||||
{
|
{
|
||||||
if (widget.isLearning())
|
widget.midiReceived(message);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +95,7 @@ void DrumPadSamplesWidget::sequencerTriggerSample(int index)
|
|||||||
qDebug() << "index out of range" << index;
|
qDebug() << "index out of range" << index;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
widgets[index].get().pressed(127);
|
widgets[index].get().pressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumPadSamplesWidget::chokeTriggered(int choke)
|
void DrumPadSamplesWidget::chokeTriggered(int choke)
|
||||||
|
@ -30,9 +30,8 @@ DrumPadSampleWidget::DrumPadSampleWidget(QWidget *parent) :
|
|||||||
|
|
||||||
connect(&m_player, &AudioPlayer::playingChanged, this, &DrumPadSampleWidget::updateStatus);
|
connect(&m_player, &AudioPlayer::playingChanged, this, &DrumPadSampleWidget::updateStatus);
|
||||||
|
|
||||||
connect(m_ui->pushButton, &QAbstractButton::pressed, this, [this](){ pressed(127); });
|
connect(m_ui->pushButtonPlay, &QAbstractButton::pressed, this, &DrumPadSampleWidget::pressed);
|
||||||
connect(m_ui->pushButton, &QAbstractButton::released, this, &DrumPadSampleWidget::released);
|
connect(m_ui->pushButtonPlay, &QAbstractButton::released, this, &DrumPadSampleWidget::released);
|
||||||
connect(m_ui->toolButtonLearn, &QAbstractButton::pressed, this, &DrumPadSampleWidget::learnPressed);
|
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
@ -41,10 +40,17 @@ DrumPadSampleWidget::~DrumPadSampleWidget() = default;
|
|||||||
|
|
||||||
void DrumPadSampleWidget::loadSettings(DrumMachineSettings &settings)
|
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_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)
|
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);
|
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
|
int DrumPadSampleWidget::speed() const
|
||||||
{
|
{
|
||||||
return m_ui->dialSpeed->value();
|
return m_ui->dialSpeed->value();
|
||||||
@ -139,10 +113,8 @@ std::optional<int> DrumPadSampleWidget::choke() const
|
|||||||
return m_file->choke;
|
return m_file->choke;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumPadSampleWidget::pressed(quint8 velocity)
|
void DrumPadSampleWidget::pressed()
|
||||||
{
|
{
|
||||||
Q_UNUSED(velocity)
|
|
||||||
|
|
||||||
m_player.restart();
|
m_player.restart();
|
||||||
|
|
||||||
if (m_file && m_file->choke && *m_file->choke)
|
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);
|
m_player.writeSamples(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumPadSampleWidget::learn(quint8 channel, quint8 note)
|
void DrumPadSampleWidget::midiReceived(const midi::MidiMessage &message)
|
||||||
{
|
{
|
||||||
setChannel(channel);
|
m_ui->pushButtonPlay->midiReceived(message);
|
||||||
setNote(note);
|
|
||||||
if (m_learning)
|
|
||||||
learnPressed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumPadSampleWidget::unsendColor()
|
void DrumPadSampleWidget::unsendColor()
|
||||||
{
|
{
|
||||||
m_sendColors = false;
|
m_sendColors = false;
|
||||||
midi::MidiMessage midiMsg;
|
|
||||||
|
|
||||||
midiMsg.channel = m_ui->channelSpinBox->value();
|
emit sendMidi(midi::MidiMessage {
|
||||||
midiMsg.cmd = midi::Command::NoteOn;
|
.channel = m_ui->pushButtonPlay->learnSetting().channel,
|
||||||
midiMsg.flag = true;
|
.cmd = m_ui->pushButtonPlay->learnSetting().cmd,
|
||||||
midiMsg.note = m_ui->noteSpinBox->value();
|
.flag = true,
|
||||||
midiMsg.velocity = 0;
|
.note = m_ui->pushButtonPlay->learnSetting().note,
|
||||||
|
.velocity = 0
|
||||||
emit sendMidi(midiMsg);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrumPadSampleWidget::sendColor()
|
void DrumPadSampleWidget::sendColor()
|
||||||
{
|
{
|
||||||
m_sendColors = true;
|
m_sendColors = true;
|
||||||
midi::MidiMessage midiMsg;
|
|
||||||
|
|
||||||
midiMsg.channel = m_ui->channelSpinBox->value();
|
uint8_t velocity;
|
||||||
midiMsg.cmd = midi::Command::NoteOn;
|
|
||||||
midiMsg.flag = true;
|
|
||||||
midiMsg.note = m_ui->noteSpinBox->value();
|
|
||||||
|
|
||||||
if (m_file && m_file->color && m_player.buffer().isValid())
|
if (m_file && m_file->color && m_player.buffer().isValid())
|
||||||
{
|
{
|
||||||
const auto &color = *m_file->color;
|
const auto &color = *m_file->color;
|
||||||
if (color == "purple")
|
if (color == "purple")
|
||||||
midiMsg.velocity = m_player.playing() ? 43 : 18;
|
velocity = m_player.playing() ? 43 : 18;
|
||||||
else if (color == "red")
|
else if (color == "red")
|
||||||
midiMsg.velocity = m_player.playing() ? 3 : 1;
|
velocity = m_player.playing() ? 3 : 1;
|
||||||
else if (color == "yellow")
|
else if (color == "yellow")
|
||||||
midiMsg.velocity = m_player.playing() ? 58 : 33;
|
velocity = m_player.playing() ? 58 : 33;
|
||||||
else if (color == "green")
|
else if (color == "green")
|
||||||
midiMsg.velocity = m_player.playing() ? 56 : 16;
|
velocity = m_player.playing() ? 56 : 16;
|
||||||
else if (color == "blue")
|
else if (color == "blue")
|
||||||
midiMsg.velocity = m_player.playing() ? 49 : 51;
|
velocity = m_player.playing() ? 49 : 51;
|
||||||
else
|
else
|
||||||
goto noColor;
|
goto noColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
noColor:
|
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()
|
void DrumPadSampleWidget::updateStatus()
|
||||||
@ -309,27 +279,6 @@ void DrumPadSampleWidget::decodingFinished(const QAudioBuffer &buffer)
|
|||||||
updateStatus();
|
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()
|
void DrumPadSampleWidget::startRequest()
|
||||||
{
|
{
|
||||||
if (m_networkAccessManager && m_file->filename)
|
if (m_networkAccessManager && m_file->filename)
|
||||||
|
@ -31,12 +31,6 @@ public:
|
|||||||
|
|
||||||
void setFile(const QString &presetId, const drumpad_presets::File &file);
|
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;
|
int speed() const;
|
||||||
void setSpeed(int speed);
|
void setSpeed(int speed);
|
||||||
|
|
||||||
@ -45,7 +39,7 @@ public:
|
|||||||
|
|
||||||
std::optional<int> choke() const;
|
std::optional<int> choke() const;
|
||||||
|
|
||||||
void pressed(quint8 velocity);
|
void pressed();
|
||||||
void released();
|
void released();
|
||||||
|
|
||||||
void forceStop();
|
void forceStop();
|
||||||
@ -55,8 +49,7 @@ public:
|
|||||||
|
|
||||||
void writeSamples(frame_t *begin, frame_t *end);
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
|
||||||
bool isLearning() const { return m_learning; }
|
void midiReceived(const midi::MidiMessage &message);
|
||||||
void learn(quint8 channel, quint8 note);
|
|
||||||
|
|
||||||
void unsendColor();
|
void unsendColor();
|
||||||
void sendColor();
|
void sendColor();
|
||||||
@ -70,7 +63,6 @@ private slots:
|
|||||||
void updateStatus();
|
void updateStatus();
|
||||||
void requestFinished();
|
void requestFinished();
|
||||||
void decodingFinished(const QAudioBuffer &buffer);
|
void decodingFinished(const QAudioBuffer &buffer);
|
||||||
void learnPressed();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startRequest();
|
void startRequest();
|
||||||
@ -92,9 +84,5 @@ private:
|
|||||||
|
|
||||||
quint8 m_padNr{};
|
quint8 m_padNr{};
|
||||||
|
|
||||||
bool m_learning{};
|
|
||||||
QColor m_oldColor;
|
|
||||||
QBrush m_oldBrush;
|
|
||||||
|
|
||||||
bool m_sendColors{};
|
bool m_sendColors{};
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>140</width>
|
<width>135</width>
|
||||||
<height>157</height>
|
<height>122</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="autoFillBackground">
|
<property name="autoFillBackground">
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="MidiButton" name="pushButton">
|
<widget class="MidiButton" name="pushButtonPlay">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>32</width>
|
<width>32</width>
|
||||||
@ -95,23 +95,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
|
@ -64,15 +64,11 @@ void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
|
|||||||
{
|
{
|
||||||
m_settings = &settings;
|
m_settings = &settings;
|
||||||
|
|
||||||
m_ui->pushButtonUp->setChannel(m_settings->drumpadChannelPrevPreset());
|
m_ui->pushButtonUp->setLearnSetting(m_settings->drumpadPrevPreset());
|
||||||
m_ui->pushButtonUp->setNote(m_settings->drumpadNotePrevPreset());
|
m_ui->pushButtonDown->setLearnSetting(m_settings->drumpadNextPreset());
|
||||||
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::learnSettingChanged, m_settings, &DrumMachineSettings::setDrumpadPrevPreset);
|
||||||
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setDrumpadNotePrevPreset);
|
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setDrumpadNextPreset);
|
||||||
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->sequencerWidget->loadSettings(settings);
|
||||||
m_ui->samplesWidget->loadSettings(settings);
|
m_ui->samplesWidget->loadSettings(settings);
|
||||||
@ -81,17 +77,17 @@ void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
|
|||||||
void DrumPadWidget::unsendColors()
|
void DrumPadWidget::unsendColors()
|
||||||
{
|
{
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -102,17 +98,17 @@ void DrumPadWidget::unsendColors()
|
|||||||
void DrumPadWidget::sendColors()
|
void DrumPadWidget::sendColors()
|
||||||
{
|
{
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -57,31 +57,27 @@ void LoopStationWidget::loadSettings(DrumMachineSettings &settings)
|
|||||||
{
|
{
|
||||||
m_settings = &settings;
|
m_settings = &settings;
|
||||||
|
|
||||||
m_ui->pushButtonUp->setChannel(m_settings->loopstationChannelPrevPreset());
|
m_ui->pushButtonUp->setLearnSetting(m_settings->loopstationPrevPreset());
|
||||||
m_ui->pushButtonUp->setNote(m_settings->loopstationNotePrevPreset());
|
m_ui->pushButtonDown->setLearnSetting(m_settings->loopstationNextPreset());
|
||||||
m_ui->pushButtonDown->setChannel(m_settings->loopstationChannelNextPreset());
|
|
||||||
m_ui->pushButtonDown->setNote(m_settings->loopstationNoteNextPreset());
|
|
||||||
|
|
||||||
connect(m_ui->pushButtonUp, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setLoopstationChannelPrevPreset);
|
connect(m_ui->pushButtonUp, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setLoopstationPrevPreset);
|
||||||
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setLoopstationNotePrevPreset);
|
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, m_settings, &DrumMachineSettings::setLoopstationNextPreset);
|
||||||
connect(m_ui->pushButtonDown, &MidiButton::channelChanged, m_settings, &DrumMachineSettings::setLoopstationChannelNextPreset);
|
|
||||||
connect(m_ui->pushButtonDown, &MidiButton::noteChanged, m_settings, &DrumMachineSettings::setLoopstationNoteNextPreset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopStationWidget::unsendColors()
|
void LoopStationWidget::unsendColors()
|
||||||
{
|
{
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -89,17 +85,17 @@ void LoopStationWidget::unsendColors()
|
|||||||
void LoopStationWidget::sendColors()
|
void LoopStationWidget::sendColors()
|
||||||
{
|
{
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -303,6 +303,10 @@ void MainWindow::updateMidiOutDevices()
|
|||||||
|
|
||||||
void MainWindow::loadSettings()
|
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->drumPadWidget->loadSettings(m_settings);
|
||||||
m_ui->loopStationWidget->loadSettings(m_settings);
|
m_ui->loopStationWidget->loadSettings(m_settings);
|
||||||
m_ui->djWidget->loadSettings(m_settings);
|
m_ui->djWidget->loadSettings(m_settings);
|
||||||
@ -311,6 +315,17 @@ void MainWindow::loadSettings()
|
|||||||
|
|
||||||
void MainWindow::unsendColors(int index)
|
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)
|
if (index == 0)
|
||||||
m_ui->drumPadWidget->unsendColors();
|
m_ui->drumPadWidget->unsendColors();
|
||||||
else if (index == 1)
|
else if (index == 1)
|
||||||
@ -323,6 +338,17 @@ void MainWindow::unsendColors(int index)
|
|||||||
|
|
||||||
void MainWindow::sendColors(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)
|
if (index == 0)
|
||||||
m_ui->drumPadWidget->sendColors();
|
m_ui->drumPadWidget->sendColors();
|
||||||
else if (index == 1)
|
else if (index == 1)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include "midicontainers.h"
|
#include "midicontainers.h"
|
||||||
|
#include "futurecpp.h"
|
||||||
|
|
||||||
MidiButton::MidiButton(QWidget *parent) :
|
MidiButton::MidiButton(QWidget *parent) :
|
||||||
QPushButton{parent}
|
QPushButton{parent}
|
||||||
@ -13,6 +14,22 @@ MidiButton::MidiButton(QWidget *parent) :
|
|||||||
auto action = new QAction{tr("Learn...")};
|
auto action = new QAction{tr("Learn...")};
|
||||||
connect(action, &QAction::triggered, this, &MidiButton::learn);
|
connect(action, &QAction::triggered, this, &MidiButton::learn);
|
||||||
addAction(action);
|
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) :
|
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()
|
void MidiButton::learn()
|
||||||
{
|
{
|
||||||
auto palette = this->palette();
|
auto palette = this->palette();
|
||||||
@ -48,38 +75,49 @@ void MidiButton::learn()
|
|||||||
|
|
||||||
void MidiButton::midiReceived(const midi::MidiMessage &message)
|
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 (m_learning)
|
||||||
{
|
{
|
||||||
if ((message.cmd != midi::Command::NoteOn && message.cmd != midi::Command::ControlChange) || message.velocity == 0)
|
if ((message.cmd != midi::Command::NoteOn && message.cmd != midi::Command::ControlChange) || message.velocity == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setChannel(message.channel);
|
setLearnSetting(MidiLearnSetting{
|
||||||
setNote(message.note);
|
.cmd = message.cmd == midi::Command::NoteOff ? midi::Command::NoteOn : message.cmd,
|
||||||
|
.channel = message.channel,
|
||||||
|
.note = message.note
|
||||||
|
});
|
||||||
|
|
||||||
learn();
|
learn();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (message.channel != m_channel || message.note != m_note)
|
if (message.channel != m_learnSetting.channel ||
|
||||||
|
message.note != m_learnSetting.note)
|
||||||
return;
|
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)
|
if (message.velocity != 0)
|
||||||
emit pressed();
|
emit pressed();
|
||||||
else
|
else
|
||||||
Q_FALLTHROUGH();
|
emit released();
|
||||||
case midi::Command::NoteOff:
|
|
||||||
emit released();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,38 +2,39 @@
|
|||||||
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#include "midilearnsetting.h"
|
||||||
|
|
||||||
namespace midi { struct MidiMessage; }
|
namespace midi { struct MidiMessage; }
|
||||||
|
class QAction;
|
||||||
|
|
||||||
class MidiButton : public QPushButton
|
class MidiButton : public QPushButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(quint8 channel READ channel WRITE setChannel NOTIFY channelChanged)
|
Q_PROPERTY(MidiLearnSetting learnSetting READ learnSetting WRITE setLearnSetting NOTIFY learnSettingChanged)
|
||||||
Q_PROPERTY(quint8 note READ note WRITE setNote NOTIFY noteChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MidiButton(QWidget *parent = nullptr);
|
explicit MidiButton(QWidget *parent = nullptr);
|
||||||
explicit MidiButton(const QString &text, QWidget *parent = nullptr);
|
explicit MidiButton(const QString &text, QWidget *parent = nullptr);
|
||||||
MidiButton(const QIcon& icon, const QString &text, QWidget *parent = nullptr);
|
MidiButton(const QIcon& icon, const QString &text, QWidget *parent = nullptr);
|
||||||
|
|
||||||
quint8 channel() const { return m_channel; }
|
MidiLearnSetting learnSetting() const { return m_learnSetting; }
|
||||||
void setChannel(quint8 channel) { if (channel == m_channel) return; emit channelChanged(m_channel = channel); }
|
void setLearnSetting(const MidiLearnSetting &learnSetting);
|
||||||
|
|
||||||
quint8 note() const { return m_note; }
|
|
||||||
void setNote(quint8 note) { if (note == m_note) return; emit noteChanged(m_note = note); }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void channelChanged(quint8 channel);
|
void learnSettingChanged(const MidiLearnSetting &learnSetting);
|
||||||
void noteChanged(quint8 note);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void learn();
|
void learn();
|
||||||
void midiReceived(const midi::MidiMessage &message);
|
void midiReceived(const midi::MidiMessage &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint8 m_channel{99};
|
MidiLearnSetting m_learnSetting;
|
||||||
quint8 m_note{99};
|
|
||||||
|
|
||||||
bool m_learning{};
|
bool m_learning{};
|
||||||
QColor m_oldColor;
|
QColor m_oldColor;
|
||||||
QBrush m_oldBrush;
|
QBrush m_oldBrush;
|
||||||
|
|
||||||
|
QAction *m_actionCmd{};
|
||||||
|
QAction *m_actionChannel{};
|
||||||
|
QAction *m_actionNote{};
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "midicontainers.h"
|
#include "midicontainers.h"
|
||||||
|
#include "futurecpp.h"
|
||||||
|
|
||||||
MidiTabWidget::MidiTabWidget(QWidget *parent) :
|
MidiTabWidget::MidiTabWidget(QWidget *parent) :
|
||||||
QTabWidget{parent}
|
QTabWidget{parent}
|
||||||
@ -14,30 +15,16 @@ MidiTabWidget::MidiTabWidget(QWidget *parent) :
|
|||||||
connect(tabBar(), &QWidget::customContextMenuRequested, this, &MidiTabWidget::showContextMenu);
|
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 (learnSetting == m_learnSettings[index])
|
||||||
if (channelNote.channel == channel)
|
|
||||||
return;
|
return;
|
||||||
emit channelChanged(index, channelNote.channel = channel);
|
emit learnSettingChanged(index, m_learnSettings[index] = learnSetting);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiTabWidget::learn(int index)
|
void MidiTabWidget::learn(int index)
|
||||||
@ -67,18 +54,21 @@ void MidiTabWidget::midiReceived(const midi::MidiMessage &message)
|
|||||||
|
|
||||||
if (m_learning)
|
if (m_learning)
|
||||||
{
|
{
|
||||||
qDebug() << "learning" << message.cmd << message.velocity << message.channel << message.note;
|
setLearnSetting(*m_learning, MidiLearnSetting{
|
||||||
setChannel(*m_learning, message.channel);
|
.cmd = message.cmd == midi::Command::NoteOff ? midi::Command::NoteOn : message.cmd,
|
||||||
setNote(*m_learning, message.note);
|
.channel = message.channel,
|
||||||
|
.note = message.note
|
||||||
|
});
|
||||||
|
|
||||||
learn(*m_learning);
|
learn(*m_learning);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "normal" << message.cmd << message.velocity << message.channel << message.note;
|
|
||||||
for (int i = 0; i < count(); i++)
|
for (int i = 0; i < count(); i++)
|
||||||
{
|
{
|
||||||
if (message.channel != m_channelNotes[i].channel ||
|
if (message.cmd != m_learnSettings[i].cmd ||
|
||||||
message.note != m_channelNotes[i].note)
|
message.channel != m_learnSettings[i].channel ||
|
||||||
|
message.note != m_learnSettings[i].note)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
setCurrentIndex(i);
|
setCurrentIndex(i);
|
||||||
@ -90,13 +80,13 @@ void MidiTabWidget::midiReceived(const midi::MidiMessage &message)
|
|||||||
void MidiTabWidget::tabInserted(int index)
|
void MidiTabWidget::tabInserted(int index)
|
||||||
{
|
{
|
||||||
QTabWidget::tabInserted(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)
|
void MidiTabWidget::tabRemoved(int index)
|
||||||
{
|
{
|
||||||
QTabWidget::tabInserted(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)
|
void MidiTabWidget::showContextMenu(const QPoint &pos)
|
||||||
@ -107,6 +97,12 @@ void MidiTabWidget::showContextMenu(const QPoint &pos)
|
|||||||
|
|
||||||
QMenu menu{tabBar()};
|
QMenu menu{tabBar()};
|
||||||
const auto learnAction = menu.addAction(tr("Learn..."));
|
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));
|
if (const auto selectedAction = menu.exec(tabBar()->mapToGlobal(pos));
|
||||||
selectedAction == learnAction)
|
selectedAction == learnAction)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "midilearnsetting.h"
|
||||||
|
|
||||||
namespace midi { struct MidiMessage; }
|
namespace midi { struct MidiMessage; }
|
||||||
|
|
||||||
class MidiTabWidget : public QTabWidget
|
class MidiTabWidget : public QTabWidget
|
||||||
@ -14,15 +16,11 @@ class MidiTabWidget : public QTabWidget
|
|||||||
public:
|
public:
|
||||||
explicit MidiTabWidget(QWidget *parent = nullptr);
|
explicit MidiTabWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
quint8 channel(int index) const;
|
MidiLearnSetting learnSetting(int index) const;
|
||||||
void setChannel(int index, quint8 channel);
|
void setLearnSetting(int index, const MidiLearnSetting &learnSetting);
|
||||||
|
|
||||||
quint8 note(int index) const;
|
|
||||||
void setNote(int index, quint8 note);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void channelChanged(int index, quint8 channel);
|
void learnSettingChanged(int index, const MidiLearnSetting &learnSetting);
|
||||||
void noteChanged(int index, quint8 note);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void learn(int index);
|
void learn(int index);
|
||||||
@ -39,10 +37,5 @@ private:
|
|||||||
std::optional<int> m_learning;
|
std::optional<int> m_learning;
|
||||||
QColor m_oldColor;
|
QColor m_oldColor;
|
||||||
|
|
||||||
struct ChannelNote
|
std::vector<MidiLearnSetting> m_learnSettings;
|
||||||
{
|
|
||||||
quint8 channel{99};
|
|
||||||
quint8 note{99};
|
|
||||||
};
|
|
||||||
std::vector<ChannelNote> m_channelNotes;
|
|
||||||
};
|
};
|
||||||
|
@ -36,23 +36,15 @@ SequencerWidget::~SequencerWidget() = default;
|
|||||||
|
|
||||||
void SequencerWidget::loadSettings(DrumMachineSettings &settings)
|
void SequencerWidget::loadSettings(DrumMachineSettings &settings)
|
||||||
{
|
{
|
||||||
m_ui->pushButtonUp->setChannel(settings.drumpadChannelPrevSequence());
|
m_ui->pushButtonUp->setLearnSetting(settings.drumpadPrevSequence());
|
||||||
m_ui->pushButtonUp->setNote(settings.drumpadNotePrevSequence());
|
m_ui->pushButtonDown->setLearnSetting(settings.drumpadNextSequence());
|
||||||
m_ui->pushButtonDown->setChannel(settings.drumpadChannelNextSequence());
|
m_ui->pushButtonPlayPause->setLearnSetting(settings.drumpadPlayPause());
|
||||||
m_ui->pushButtonDown->setNote(settings.drumpadNoteNextSequence());
|
m_ui->pushButtonStop->setLearnSetting(settings.drumpadStop());
|
||||||
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::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadPrevSequence);
|
||||||
connect(m_ui->pushButtonUp, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNotePrevSequence);
|
connect(m_ui->pushButtonDown, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadNextSequence);
|
||||||
connect(m_ui->pushButtonDown, &MidiButton::channelChanged, &settings, &DrumMachineSettings::setDrumpadChannelNextSequence);
|
connect(m_ui->pushButtonPlayPause, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadPlayPause);
|
||||||
connect(m_ui->pushButtonDown, &MidiButton::noteChanged, &settings, &DrumMachineSettings::setDrumpadNoteNextSequence);
|
connect(m_ui->pushButtonStop, &MidiButton::learnSettingChanged, &settings, &DrumMachineSettings::setDrumpadStop);
|
||||||
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()
|
void SequencerWidget::unsendColors()
|
||||||
@ -60,31 +52,31 @@ void SequencerWidget::unsendColors()
|
|||||||
m_sendColors = false;
|
m_sendColors = false;
|
||||||
|
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonPlayPause->channel(),
|
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonPlayPause->note(),
|
.note = m_ui->pushButtonPlayPause->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonStop->channel(),
|
.channel = m_ui->pushButtonStop->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonStop->note(),
|
.note = m_ui->pushButtonStop->learnSetting().note,
|
||||||
.velocity = 0
|
.velocity = 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -94,31 +86,31 @@ void SequencerWidget::sendColors()
|
|||||||
m_sendColors = true;
|
m_sendColors = true;
|
||||||
|
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonUp->channel(),
|
.channel = m_ui->pushButtonUp->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonUp->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonUp->note(),
|
.note = m_ui->pushButtonUp->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonDown->channel(),
|
.channel = m_ui->pushButtonDown->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonDown->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonDown->note(),
|
.note = m_ui->pushButtonDown->learnSetting().note,
|
||||||
.velocity = 127
|
.velocity = 127
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonPlayPause->channel(),
|
.channel = m_ui->pushButtonPlayPause->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonPlayPause->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonPlayPause->note(),
|
.note = m_ui->pushButtonPlayPause->learnSetting().note,
|
||||||
.velocity = 60
|
.velocity = 60
|
||||||
});
|
});
|
||||||
emit sendMidi(midi::MidiMessage {
|
emit sendMidi(midi::MidiMessage {
|
||||||
.channel = m_ui->pushButtonStop->channel(),
|
.channel = m_ui->pushButtonStop->learnSetting().channel,
|
||||||
.cmd = midi::Command::NoteOn,
|
.cmd = m_ui->pushButtonStop->learnSetting().cmd,
|
||||||
.flag = true,
|
.flag = true,
|
||||||
.note = m_ui->pushButtonStop->note(),
|
.note = m_ui->pushButtonStop->learnSetting().note,
|
||||||
.velocity = 3
|
.velocity = 3
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user