From 873c8b204ab70622f6e231556cc94d3aab1889ce Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 16 Jan 2019 23:00:53 +0100 Subject: [PATCH] Support non-binary MIDI lights (ie., with an on-velocity different from 1). No UI support yet. Most likely we'll only have UI support in Futatabi. --- futatabi/midi_mapper.cpp | 3 ++- nageru/midi_mapper.cpp | 4 ++-- nageru/midi_mapper.h | 3 +-- shared/midi_device.cpp | 18 +++++++----------- shared/midi_device.h | 7 +++---- shared/midi_mapper_util.h | 4 ++-- shared/midi_mapping.proto | 1 + 7 files changed, 18 insertions(+), 22 deletions(-) diff --git a/futatabi/midi_mapper.cpp b/futatabi/midi_mapper.cpp index d1cfea2..849c72c 100644 --- a/futatabi/midi_mapper.cpp +++ b/futatabi/midi_mapper.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "defs.h" @@ -205,7 +206,7 @@ void MIDIMapper::refresh_lights() void MIDIMapper::update_lights_lock_held() { - set active_lights; // Desired state. + map active_lights; // Desired state. if (current_controller_bank == 0) { activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank1IsSelectedFieldNumber, &active_lights); } diff --git a/nageru/midi_mapper.cpp b/nageru/midi_mapper.cpp index d111a7a..1fdb72e 100644 --- a/nageru/midi_mapper.cpp +++ b/nageru/midi_mapper.cpp @@ -318,7 +318,7 @@ void MIDIMapper::update_lights_lock_held() return; } - set active_lights; // Desired state. + map active_lights; // Desired state. if (current_controller_bank == 0) { activate_lights_all_buses(MIDIMappingBusProto::kBank1IsSelectedFieldNumber, &active_lights); } @@ -363,7 +363,7 @@ void MIDIMapper::update_lights_lock_held() midi_device.update_lights(active_lights); } -void MIDIMapper::activate_lights_all_buses(int field_number, set *active_lights) +void MIDIMapper::activate_lights_all_buses(int field_number, map *active_lights) { for (size_t bus_idx = 0; bus_idx < size_t(mapping_proto->bus_mapping_size()); ++bus_idx) { const MIDIMappingBusProto &bus_mapping = mapping_proto->bus_mapping(bus_idx); diff --git a/nageru/midi_mapper.h b/nageru/midi_mapper.h index a259943..3ecdee2 100644 --- a/nageru/midi_mapper.h +++ b/nageru/midi_mapper.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -110,7 +109,7 @@ private: void update_highlights(); void update_lights_lock_held(); - void activate_lights_all_buses(int field_number, std::set *active_lights); + void activate_lights_all_buses(int field_number, std::map *active_lights); std::atomic should_quit{false}; int should_quit_fd; diff --git a/shared/midi_device.cpp b/shared/midi_device.cpp index ac0fea2..a232961 100644 --- a/shared/midi_device.cpp +++ b/shared/midi_device.cpp @@ -233,17 +233,12 @@ void MIDIDevice::subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_ } // The current status of the device is unknown, so refresh it. - set active_lights; - for (const auto &it : current_light_status) { - if (it.second) { - active_lights.insert(it.first); - } - } + map active_lights = move(current_light_status); current_light_status.clear(); update_lights_lock_held(active_lights); } -void MIDIDevice::update_lights_lock_held(const set &active_lights) +void MIDIDevice::update_lights_lock_held(const map &active_lights) { if (alsa_seq == nullptr) { return; @@ -251,9 +246,10 @@ void MIDIDevice::update_lights_lock_held(const set &active_lights) unsigned num_events = 0; for (unsigned note_num = 1; note_num <= 127; ++note_num) { // Note: Pitch bend is ignored. - bool active = active_lights.count(note_num); + const auto it = active_lights.find(note_num); + uint8_t velocity = (it == active_lights.end()) ? 0 : it->second; if (current_light_status.count(note_num) && - current_light_status[note_num] == active) { + current_light_status[note_num] == velocity) { // Already known to be in the desired state. continue; } @@ -270,9 +266,9 @@ void MIDIDevice::update_lights_lock_held(const set &active_lights) // For some reason, not all devices respond to note off. // Use note-on with velocity of 0 (which is equivalent) instead. - snd_seq_ev_set_noteon(&ev, /*channel=*/0, note_num, active ? 1 : 0); + snd_seq_ev_set_noteon(&ev, /*channel=*/0, note_num, velocity); WARN_ON_ERROR("snd_seq_event_output", snd_seq_event_output(alsa_seq, &ev)); - current_light_status[note_num] = active; + current_light_status[note_num] = velocity; } WARN_ON_ERROR("snd_seq_drain_output", snd_seq_drain_output(alsa_seq)); } diff --git a/shared/midi_device.h b/shared/midi_device.h index 4984439..9c76d18 100644 --- a/shared/midi_device.h +++ b/shared/midi_device.h @@ -7,7 +7,6 @@ #include #include #include -#include #include typedef struct snd_seq_addr snd_seq_addr_t; @@ -33,7 +32,7 @@ public: ~MIDIDevice(); void start_thread(); - void update_lights(const std::set &active_lights) + void update_lights(const std::map &active_lights) { std::lock_guard lock(mu); update_lights_lock_held(active_lights); @@ -43,7 +42,7 @@ private: void thread_func(); void handle_event(snd_seq_t *seq, snd_seq_event_t *event); void subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_t &addr); - void update_lights_lock_held(const std::set &active_lights); + void update_lights_lock_held(const std::map &active_lights); std::atomic should_quit{false}; int should_quit_fd; @@ -52,7 +51,7 @@ private: MIDIReceiver *receiver; // Under . std::thread midi_thread; - std::map current_light_status; // Keyed by note number. Under . + std::map current_light_status; // Keyed by note number. Under . snd_seq_t *alsa_seq{nullptr}; // Under . int alsa_queue_id{-1}; // Under . std::atomic num_subscribed_ports{0}; diff --git a/shared/midi_mapper_util.h b/shared/midi_mapper_util.h index 5b66b83..07f2a53 100644 --- a/shared/midi_mapper_util.h +++ b/shared/midi_mapper_util.h @@ -49,7 +49,7 @@ inline bool match_bank_helper(const Proto &msg, int bank_field_number, int bank) // Find what MIDI note the given light (as given by field_number) is mapped to, and enable it. template -void activate_mapped_light(const Proto &msg, int field_number, std::set *active_lights) +void activate_mapped_light(const Proto &msg, int field_number, std::map *active_lights) { using namespace google::protobuf; const FieldDescriptor *descriptor = msg.GetDescriptor()->FindFieldByNumber(field_number); @@ -59,7 +59,7 @@ void activate_mapped_light(const Proto &msg, int field_number, std::set(reflection->GetMessage(msg, descriptor)); - active_lights->insert(light_proto.note_number()); + active_lights->emplace(light_proto.note_number(), light_proto.velocity()); } inline double map_controller_to_float(int controller, int val) diff --git a/shared/midi_mapping.proto b/shared/midi_mapping.proto index 95ac590..8f34386 100644 --- a/shared/midi_mapping.proto +++ b/shared/midi_mapping.proto @@ -16,4 +16,5 @@ message MIDIButtonProto { message MIDILightProto { required int32 note_number = 1; + optional int32 velocity = 2 [default=1]; } -- 2.39.2