mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
177 lines
4.6 KiB
C++
177 lines
4.6 KiB
C++
#pragma once
|
|
#include <QComboBox>
|
|
#include <message-dispatcher.hpp>
|
|
#include <obs-data.h>
|
|
#include <variable-number.hpp>
|
|
#include <variable-spinbox.hpp>
|
|
#include <variable-string.hpp>
|
|
|
|
#define LIBREMIDI_HEADER_ONLY 1
|
|
#include <libremidi/libremidi.hpp>
|
|
|
|
namespace advss {
|
|
|
|
class MidiMessage;
|
|
using MidiMessageBuffer = std::shared_ptr<MessageBuffer<MidiMessage>>;
|
|
using MidiMessageDispatcher = MessageDispatcher<MidiMessage>;
|
|
|
|
// Based on https://github.com/nhielost/obs-midi-mg MMGMessage
|
|
class MidiMessage {
|
|
public:
|
|
MidiMessage() = default;
|
|
MidiMessage(const libremidi::message &message);
|
|
|
|
void Save(obs_data_t *obj) const;
|
|
void Load(obs_data_t *obj);
|
|
|
|
bool Matches(const MidiMessage &) const;
|
|
|
|
static std::string ToString(const libremidi::message &msg);
|
|
static std::string MidiTypeToString(libremidi::message_type type);
|
|
static std::string GetMidiType(const libremidi::message &msg);
|
|
static int GetMidiNote(const libremidi::message &msg);
|
|
static int GetMidiValue(const libremidi::message &msg);
|
|
|
|
std::string ToString() const;
|
|
libremidi::message_type Type() const { return _type; }
|
|
int Channel() const { return _channel; }
|
|
int Note() const { return _note; }
|
|
int Value() const { return _value; }
|
|
|
|
void ResolveVariables();
|
|
|
|
private:
|
|
// Values which don't appear for channel, note, and value will be used
|
|
// to indicate whether this part of the message is optional and can be
|
|
// disregarded (e.g.during comparison using Matches())
|
|
static const int optionalChannelIndicator = 0;
|
|
static const int optionalNoteIndicator = -1;
|
|
static const int optionalValueIndicator = -1;
|
|
|
|
bool _typeIsOptional = true;
|
|
libremidi::message_type _type = libremidi::message_type::INVALID;
|
|
NumberVariable<int> _channel = optionalChannelIndicator;
|
|
NumberVariable<int> _note = optionalNoteIndicator;
|
|
NumberVariable<int> _value = optionalValueIndicator;
|
|
|
|
friend class MidiMessageSelection;
|
|
};
|
|
|
|
enum class MidiDeviceType {
|
|
INPUT,
|
|
OUTPUT,
|
|
};
|
|
|
|
class MidiDeviceInstance {
|
|
public:
|
|
static MidiDeviceInstance *GetDeviceAndOpen(MidiDeviceType type,
|
|
const std::string &);
|
|
static MidiDeviceInstance *GetDeviceAndOpen(MidiDeviceType type,
|
|
int port);
|
|
static MidiDeviceInstance *GetDevice(const libremidi::input_port &p);
|
|
static MidiDeviceInstance *GetDevice(const libremidi::output_port &p);
|
|
|
|
static void ResetAllDevices();
|
|
|
|
bool OpenPort();
|
|
void ClosePort();
|
|
|
|
private:
|
|
MidiDeviceInstance() = default;
|
|
~MidiDeviceInstance() = default;
|
|
bool IsOpened() const;
|
|
bool SendMessge(const MidiMessage &);
|
|
[[nodiscard]] MidiMessageBuffer RegisterForMidiMessages();
|
|
void ReceiveMidiMessage(libremidi::message &&);
|
|
|
|
static std::map<std::pair<MidiDeviceType, std::string>,
|
|
MidiDeviceInstance *>
|
|
devices;
|
|
|
|
MidiDeviceType _type = MidiDeviceType::INPUT;
|
|
std::string _name;
|
|
libremidi::midi_in _in =
|
|
libremidi::midi_in(libremidi::input_configuration{
|
|
[this](libremidi::message &&message) {
|
|
ReceiveMidiMessage(std::move(message));
|
|
}});
|
|
libremidi::midi_out _out =
|
|
libremidi::midi_out(libremidi::output_configuration());
|
|
MidiMessageDispatcher _dispatcher;
|
|
|
|
friend class MidiDevice;
|
|
};
|
|
|
|
class MidiDevice {
|
|
public:
|
|
MidiDevice() = default;
|
|
|
|
void Save(obs_data_t *obj) const;
|
|
void Load(obs_data_t *obj);
|
|
|
|
bool SendMessge(const MidiMessage &) const;
|
|
[[nodiscard]] MidiMessageBuffer RegisterForMidiMessages() const;
|
|
|
|
std::string Name() const;
|
|
|
|
bool DeviceSelected() const { return !!_dev; }
|
|
|
|
private:
|
|
MidiDeviceType _type = MidiDeviceType::INPUT;
|
|
std::string _name;
|
|
MidiDeviceInstance *_dev = nullptr;
|
|
|
|
friend class MidiDeviceSelection;
|
|
};
|
|
|
|
class MidiMessageSelection : public QWidget {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
MidiMessageSelection(QWidget *parent);
|
|
void SetMessage(const MidiMessage &);
|
|
|
|
private slots:
|
|
void TypeChanged(const QString &);
|
|
void ChannelChanged(const NumberVariable<int> &);
|
|
void NoteChanged(const NumberVariable<int> &);
|
|
void NoteStringIdxChanged(int);
|
|
void ShowNote(bool);
|
|
void ValueChanged(const NumberVariable<int> &);
|
|
|
|
signals:
|
|
void MidiMessageChanged(const MidiMessage &);
|
|
|
|
private:
|
|
static libremidi::message_type TextToMidiType(const QString &);
|
|
|
|
QComboBox *_type;
|
|
VariableSpinBox *_channel;
|
|
VariableSpinBox *_noteValue;
|
|
QComboBox *_noteString;
|
|
QPushButton *_noteValueStringToggle;
|
|
VariableSpinBox *_value;
|
|
|
|
MidiMessage _currentSelection;
|
|
};
|
|
|
|
class MidiDeviceSelection : public QComboBox {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
MidiDeviceSelection(QWidget *parent, MidiDeviceType);
|
|
void SetDevice(const MidiDevice &);
|
|
|
|
private slots:
|
|
void IdxChangedHelper(int);
|
|
signals:
|
|
void DeviceSelectionChanged(const MidiDevice &);
|
|
|
|
private:
|
|
const MidiDeviceType _type;
|
|
};
|
|
|
|
QStringList GetAllNotes();
|
|
|
|
} // namespace advss
|