Added new struct for remote events
This commit is contained in:
parent
8d9ac72131
commit
bb8f0c5602
8 changed files with 118 additions and 46 deletions
|
@ -30,7 +30,7 @@ import MuseScore.Midi 1.0
|
|||
Dialog {
|
||||
id: root
|
||||
|
||||
signal mapToValueRequested(int value)
|
||||
signal mapToEventRequested(var event)
|
||||
|
||||
title: qsTrc("midi", "MIDI Remote Control")
|
||||
|
||||
|
@ -40,7 +40,7 @@ Dialog {
|
|||
standardButtons: Dialog.NoButton
|
||||
|
||||
function startEdit(action) {
|
||||
model.load(action.mappedValue)
|
||||
model.load(action.mappedType, action.mappedValue)
|
||||
open()
|
||||
|
||||
actionNameLabel.text = action.title
|
||||
|
@ -117,7 +117,7 @@ Dialog {
|
|||
enabled: mappingField.hasText
|
||||
|
||||
onClicked: {
|
||||
root.mapToValueRequested(model.inputedValue())
|
||||
root.mapToEventRequested(model.inputedEvent())
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,8 @@ Item {
|
|||
editMappingDialog.startEdit(mappingsModel.currentAction())
|
||||
}
|
||||
|
||||
onMapToValueRequested: {
|
||||
mappingsModel.mapCurrentActionToMidiValue(value)
|
||||
onMapToEventRequested: {
|
||||
mappingsModel.mapCurrentActionToMidiEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "translation.h"
|
||||
|
||||
using namespace mu::midi;
|
||||
using namespace mu::shortcuts;
|
||||
|
||||
static const QString WAITING_STATE = qtrc("midi", "Waiting...");
|
||||
|
||||
|
@ -39,37 +40,54 @@ EditMidiMappingModel::~EditMidiMappingModel()
|
|||
midiRemote()->setIsSettingMode(false);
|
||||
}
|
||||
|
||||
void EditMidiMappingModel::load(int originValue)
|
||||
void EditMidiMappingModel::load(int originType, int originValue)
|
||||
{
|
||||
midiRemote()->setIsSettingMode(true);
|
||||
|
||||
midiInPort()->eventReceived().onReceive(this, [this](const std::pair<tick_t, Event>& event) {
|
||||
if (event.second.opcode() != Event::Opcode::NoteOn && event.second.opcode() != Event::Opcode::ControlChange) {
|
||||
return;
|
||||
if (event.second.opcode() == Event::Opcode::NoteOn || event.second.opcode() == Event::Opcode::ControlChange) {
|
||||
LOGD() << "==== recive " << QString::fromStdString(event.second.to_string());
|
||||
|
||||
auto remoteEvent = [](const Event& midiEvent) { // todo
|
||||
RemoteEvent event;
|
||||
bool isNote = midiEvent.isOpcodeIn({ Event::Opcode::NoteOff, Event::Opcode::NoteOn });
|
||||
bool isController = midiEvent.isOpcodeIn({ Event::Opcode::ControlChange });
|
||||
if (isNote) {
|
||||
event.type = RemoteEventType::Note;
|
||||
event.value = midiEvent.note();
|
||||
} else if (isController) {
|
||||
event.type = RemoteEventType::Controller;
|
||||
event.value = midiEvent.index();
|
||||
}
|
||||
|
||||
LOGD() << "==== recive " << QString::fromStdString(event.second.to_string());
|
||||
m_value = event.second.to_MIDI10Package();
|
||||
return event;
|
||||
};
|
||||
|
||||
m_event = remoteEvent(event.second);
|
||||
emit mappingTitleChanged(mappingTitle());
|
||||
}
|
||||
});
|
||||
|
||||
m_value = originValue;
|
||||
m_event = RemoteEvent(static_cast<RemoteEventType>(originType), originValue);
|
||||
emit mappingTitleChanged(mappingTitle());
|
||||
}
|
||||
|
||||
QString EditMidiMappingModel::mappingTitle() const
|
||||
{
|
||||
MidiDeviceID currentMidiInDeviceId = midiInPort()->deviceID();
|
||||
if (currentMidiInDeviceId.empty() || m_value == 0) {
|
||||
if (currentMidiInDeviceId.empty() || !m_event.isValid()) {
|
||||
return WAITING_STATE;
|
||||
}
|
||||
|
||||
return deviceName(currentMidiInDeviceId) + " > " + valueName(m_value);
|
||||
return deviceName(currentMidiInDeviceId) + " > " + eventName(m_event);
|
||||
}
|
||||
|
||||
int EditMidiMappingModel::inputedValue() const
|
||||
QVariant EditMidiMappingModel::inputedEvent() const
|
||||
{
|
||||
return m_value;
|
||||
QVariantMap obj;
|
||||
obj["type"] = static_cast<int>(m_event.type);
|
||||
obj["value"] = m_event.value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
QString EditMidiMappingModel::deviceName(const MidiDeviceID& deviceId) const
|
||||
|
@ -83,16 +101,14 @@ QString EditMidiMappingModel::deviceName(const MidiDeviceID& deviceId) const
|
|||
return QString();
|
||||
}
|
||||
|
||||
QString EditMidiMappingModel::valueName(int value) const
|
||||
QString EditMidiMappingModel::eventName(const RemoteEvent& event) const
|
||||
{
|
||||
QString title;
|
||||
|
||||
Event event = Event::fromMIDI10Package(value);
|
||||
|
||||
if (event.opcode() == Event::Opcode::NoteOn) {
|
||||
return qtrc("midi", "Note ") + QString::number(event.note());
|
||||
} else if (event.opcode() == Event::Opcode::ControlChange) {
|
||||
return qtrc("midi", "Controller ") + QString::number(event.index());
|
||||
if (event.type == RemoteEventType::Note) {
|
||||
return qtrc("midi", "Note ") + QString::number(event.value);
|
||||
} else if (event.type == RemoteEventType::Controller) {
|
||||
return qtrc("midi", "Controller ") + QString::number(event.value);
|
||||
}
|
||||
|
||||
return qtrc("midi", "None"); // todo
|
||||
|
|
|
@ -46,17 +46,17 @@ public:
|
|||
|
||||
QString mappingTitle() const;
|
||||
|
||||
Q_INVOKABLE void load(int originValue);
|
||||
Q_INVOKABLE int inputedValue() const;
|
||||
Q_INVOKABLE void load(int originType, int originValue);
|
||||
Q_INVOKABLE QVariant inputedEvent() const;
|
||||
|
||||
signals:
|
||||
void mappingTitleChanged(const QString& title);
|
||||
|
||||
private:
|
||||
QString deviceName(const MidiDeviceID& deviceId) const;
|
||||
QString valueName(int value) const;
|
||||
QString eventName(const shortcuts::RemoteEvent& event) const;
|
||||
|
||||
int m_value = -1;
|
||||
shortcuts::RemoteEvent m_event;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ static const QString TITLE_KEY("title");
|
|||
static const QString ICON_KEY("icon");
|
||||
static const QString STATUS_KEY("status");
|
||||
static const QString ENABLED_KEY("enabled");
|
||||
static const QString MAPPED_TYPE_KEY("mappedType");
|
||||
static const QString MAPPED_VALUE_KEY("mappedValue");
|
||||
|
||||
inline std::vector<ActionCode> allMidiActions()
|
||||
|
@ -81,6 +82,7 @@ QVariant MidiDeviceMappingModel::data(const QModelIndex& index, int role) const
|
|||
case RoleIcon: return obj[ICON_KEY].toInt();
|
||||
case RoleStatus: return obj[STATUS_KEY].toString();
|
||||
case RoleEnabled: return obj[ENABLED_KEY].toBool();
|
||||
case RoleMappedType: return obj[MAPPED_TYPE_KEY].toInt();
|
||||
case RoleMappedValue: return obj[MAPPED_VALUE_KEY].toInt();
|
||||
}
|
||||
|
||||
|
@ -96,7 +98,8 @@ QVariantMap MidiDeviceMappingModel::midiMappingToObject(const MidiMapping& midiM
|
|||
obj[TITLE_KEY] = action.title;
|
||||
obj[ICON_KEY] = static_cast<int>(action.iconCode);
|
||||
obj[STATUS_KEY] = midiMapping.isValid() ? "Active" : "Inactive";
|
||||
obj[MAPPED_VALUE_KEY] = midiMapping.isValid() ? midiMapping.event.to_MIDI10Package() : 0;
|
||||
obj[MAPPED_TYPE_KEY] = static_cast<int>(midiMapping.event.type);
|
||||
obj[MAPPED_VALUE_KEY] = midiMapping.event.value;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -113,6 +116,7 @@ QHash<int, QByteArray> MidiDeviceMappingModel::roleNames() const
|
|||
{ RoleIcon, ICON_KEY.toUtf8() },
|
||||
{ RoleStatus, STATUS_KEY.toUtf8() },
|
||||
{ RoleEnabled, ENABLED_KEY.toUtf8() },
|
||||
{ RoleMappedType, MAPPED_TYPE_KEY.toUtf8() },
|
||||
{ RoleMappedValue, MAPPED_VALUE_KEY.toUtf8() }
|
||||
};
|
||||
}
|
||||
|
@ -124,14 +128,14 @@ void MidiDeviceMappingModel::load()
|
|||
|
||||
shortcuts::MidiMappingList midiMappings = midiRemote()->midiMappings();
|
||||
|
||||
auto midiEvent = [&midiMappings](const ActionCode& actionCode) {
|
||||
auto remoteEvent = [&midiMappings](const ActionCode& actionCode) {
|
||||
for (const MidiMapping& midiMapping : midiMappings) {
|
||||
if (midiMapping.action == actionCode) {
|
||||
return midiMapping.event;
|
||||
}
|
||||
}
|
||||
|
||||
return Event();
|
||||
return RemoteEvent();
|
||||
};
|
||||
|
||||
for (const ActionCode& actionCode : allMidiActions()) {
|
||||
|
@ -139,7 +143,7 @@ void MidiDeviceMappingModel::load()
|
|||
|
||||
if (action.isValid()) {
|
||||
MidiMapping midiMapping(actionCode);
|
||||
midiMapping.event = midiEvent(actionCode);
|
||||
midiMapping.event = remoteEvent(actionCode);
|
||||
m_midiMappings.push_back(midiMapping);
|
||||
}
|
||||
}
|
||||
|
@ -217,8 +221,12 @@ QVariant MidiDeviceMappingModel::currentAction() const
|
|||
return midiMappingToObject(midiMapping);
|
||||
}
|
||||
|
||||
void MidiDeviceMappingModel::mapCurrentActionToMidiValue(int value)
|
||||
void MidiDeviceMappingModel::mapCurrentActionToMidiEvent(const QVariant& event)
|
||||
{
|
||||
m_midiMappings[m_selection.indexes().first().row()].event = Event::fromMIDI10Package(value);
|
||||
QVariantMap eventMap = event.toMap();
|
||||
RemoteEventType type = static_cast<RemoteEventType>(eventMap["type"].toInt());
|
||||
int value = eventMap["value"].toInt();
|
||||
|
||||
m_midiMappings[m_selection.indexes().first().row()].event = RemoteEvent(type, value);
|
||||
emit dataChanged(m_selection.indexes().first(), m_selection.indexes().first());
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
Q_INVOKABLE void clearAllActions();
|
||||
|
||||
Q_INVOKABLE QVariant currentAction() const;
|
||||
Q_INVOKABLE void mapCurrentActionToMidiValue(int value);
|
||||
Q_INVOKABLE void mapCurrentActionToMidiEvent(const QVariant& event);
|
||||
|
||||
public slots:
|
||||
void setUseRemoteControl(bool value);
|
||||
|
@ -82,6 +82,7 @@ private:
|
|||
RoleIcon,
|
||||
RoleEnabled,
|
||||
RoleStatus,
|
||||
RoleMappedType,
|
||||
RoleMappedValue
|
||||
};
|
||||
|
||||
|
|
|
@ -28,11 +28,13 @@
|
|||
|
||||
using namespace mu::shortcuts;
|
||||
using namespace mu::framework;
|
||||
using namespace mu::midi;
|
||||
|
||||
constexpr std::string_view MIDIMAPPING_TAG("MidiMapping");
|
||||
constexpr std::string_view EVENT_TAG("Event");
|
||||
constexpr std::string_view MAPPING_ACTION_CODE_TAG("key");
|
||||
constexpr std::string_view MAPPING_EVENT_DATA_TAG("EventData");
|
||||
constexpr std::string_view MAPPING_EVENT_TYPE_TAG("EventType");
|
||||
constexpr std::string_view MAPPING_EVENT_VALUE_TAG("EventValue");
|
||||
|
||||
void MidiRemote::load()
|
||||
{
|
||||
|
@ -69,20 +71,37 @@ bool MidiRemote::isSettingMode() const
|
|||
return m_isSettingMode;
|
||||
}
|
||||
|
||||
void MidiRemote::setCurrentActionEvent(const midi::Event& ev)
|
||||
void MidiRemote::setCurrentActionEvent(const Event& ev)
|
||||
{
|
||||
UNUSED(ev);
|
||||
NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
mu::Ret MidiRemote::process(const midi::Event& ev)
|
||||
mu::Ret MidiRemote::process(const Event& ev)
|
||||
{
|
||||
if (isSettingMode()) {
|
||||
return make_ret(Ret::Code::Ok); // todo
|
||||
}
|
||||
|
||||
auto remoteEvent = [](const Event& midiEvent) { // todo
|
||||
RemoteEvent event;
|
||||
bool isNote = midiEvent.isOpcodeIn({ Event::Opcode::NoteOff, Event::Opcode::NoteOn });
|
||||
bool isController = midiEvent.isOpcodeIn({ Event::Opcode::ControlChange });
|
||||
if (isNote) {
|
||||
event.type = RemoteEventType::Note;
|
||||
event.value = midiEvent.note();
|
||||
} else if (isController) {
|
||||
event.type = RemoteEventType::Controller;
|
||||
event.value = midiEvent.index();
|
||||
}
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
RemoteEvent event = remoteEvent(ev);
|
||||
|
||||
for (const MidiMapping& midiMapping : m_midiMappings) {
|
||||
if (midiMapping.event == ev) {
|
||||
if (midiMapping.event == event) {
|
||||
dispatcher()->dispatch(midiMapping.action);
|
||||
return make_ret(Ret::Code::Ok);
|
||||
}
|
||||
|
@ -127,8 +146,10 @@ MidiMapping MidiRemote::readMidiMapping(XmlReader& reader) const
|
|||
|
||||
if (tag == MAPPING_ACTION_CODE_TAG) {
|
||||
midiMapping.action = reader.readString();
|
||||
} else if (tag == MAPPING_EVENT_DATA_TAG) {
|
||||
midiMapping.event.fromMIDI10Package(reader.readInt());
|
||||
} else if (tag == MAPPING_EVENT_TYPE_TAG) {
|
||||
midiMapping.event.type = static_cast<RemoteEventType>(reader.readInt());
|
||||
} else if (tag == MAPPING_EVENT_VALUE_TAG) {
|
||||
midiMapping.event.value = reader.readInt();
|
||||
} else {
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
@ -161,6 +182,7 @@ void MidiRemote::writeMidiMapping(XmlWriter& writer, const MidiMapping& midiMapp
|
|||
{
|
||||
writer.writeStartElement(EVENT_TAG);
|
||||
writer.writeTextElement(MAPPING_ACTION_CODE_TAG, midiMapping.action);
|
||||
writer.writeTextElement(MAPPING_EVENT_DATA_TAG, std::to_string(midiMapping.event.to_MIDI10Package()));
|
||||
writer.writeTextElement(MAPPING_EVENT_TYPE_TAG, std::to_string(midiMapping.event.type));
|
||||
writer.writeTextElement(MAPPING_EVENT_VALUE_TAG, std::to_string(midiMapping.event.value));
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
|
|
@ -48,9 +48,34 @@ struct Shortcut
|
|||
|
||||
using ShortcutList = std::list<Shortcut>;
|
||||
|
||||
enum RemoteEventType {
|
||||
Undefined = 0,
|
||||
Note,
|
||||
Controller
|
||||
};
|
||||
|
||||
struct RemoteEvent {
|
||||
RemoteEventType type = RemoteEventType::Undefined;
|
||||
int value = -1;
|
||||
|
||||
RemoteEvent() = default;
|
||||
RemoteEvent(RemoteEventType type, int value)
|
||||
: type(type), value(value) {}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return type != RemoteEventType::Undefined && value != -1;
|
||||
}
|
||||
|
||||
bool operator ==(const RemoteEvent& other) const
|
||||
{
|
||||
return type == other.type && value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
struct MidiMapping {
|
||||
std::string action;
|
||||
midi::Event event;
|
||||
RemoteEvent event;
|
||||
|
||||
MidiMapping() = default;
|
||||
MidiMapping(const std::string& action)
|
||||
|
@ -58,12 +83,12 @@ struct MidiMapping {
|
|||
|
||||
bool isValid() const
|
||||
{
|
||||
return !action.empty() && event;
|
||||
return !action.empty() && event.isValid();
|
||||
}
|
||||
|
||||
bool operator ==(const MidiMapping& mm) const
|
||||
bool operator ==(const MidiMapping& other) const
|
||||
{
|
||||
return action == mm.action && mm.event == event;
|
||||
return action == other.action && other.event == event;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue