Added new struct for remote events

This commit is contained in:
Eism 2021-06-08 11:18:28 +02:00
parent 8d9ac72131
commit bb8f0c5602
8 changed files with 118 additions and 46 deletions

View file

@ -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()
}
}

View file

@ -40,8 +40,8 @@ Item {
editMappingDialog.startEdit(mappingsModel.currentAction())
}
onMapToValueRequested: {
mappingsModel.mapCurrentActionToMidiValue(value)
onMapToEventRequested: {
mappingsModel.mapCurrentActionToMidiEvent(event)
}
}

View file

@ -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());
LOGD() << "==== recive " << QString::fromStdString(event.second.to_string());
m_value = event.second.to_MIDI10Package();
emit mappingTitleChanged(mappingTitle());
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;
};
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

View file

@ -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;
};
}

View file

@ -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());
}

View file

@ -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
};

View file

@ -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();
}

View file

@ -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;
}
};