1 #include "midi_mapper.h"
3 #include <alsa/asoundlib.h>
7 #include <google/protobuf/descriptor.h>
8 #include <google/protobuf/io/zero_copy_stream_impl.h>
9 #include <google/protobuf/message.h>
10 #include <google/protobuf/text_format.h>
15 #include <sys/eventfd.h>
22 #include "futatabi_midi_mapping.pb.h"
23 #include "shared/midi_mapper_util.h"
24 #include "shared/text_proto.h"
26 using namespace google::protobuf;
28 using namespace std::placeholders;
30 MIDIMapper::MIDIMapper(ControllerReceiver *receiver)
31 : receiver(receiver), mapping_proto(new MIDIMappingProto), midi_device(this)
35 MIDIMapper::~MIDIMapper() {}
37 bool load_midi_mapping_from_file(const string &filename, MIDIMappingProto *new_mapping)
39 return load_proto_from_file(filename, new_mapping);
42 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const string &filename)
44 return save_proto_to_file(mapping_proto, filename);
47 void MIDIMapper::set_midi_mapping(const MIDIMappingProto &new_mapping)
49 lock_guard<mutex> lock(mu);
51 mapping_proto->CopyFrom(new_mapping);
53 mapping_proto.reset(new MIDIMappingProto(new_mapping));
56 num_controller_banks = min(max(mapping_proto->num_controller_banks(), 1), 5);
57 current_controller_bank = 0;
60 void MIDIMapper::start_thread()
62 midi_device.start_thread();
65 const MIDIMappingProto &MIDIMapper::get_current_mapping() const
67 lock_guard<mutex> lock(mu);
68 return *mapping_proto;
71 ControllerReceiver *MIDIMapper::set_receiver(ControllerReceiver *new_receiver)
73 lock_guard<mutex> lock(mu);
74 swap(receiver, new_receiver);
75 return new_receiver; // Now old receiver.
78 void MIDIMapper::controller_received(int controller, int value_int)
80 int delta_value = value_int - 64; // For infinite controllers such as jog.
82 receiver->controller_changed(controller);
84 match_controller(controller, MIDIMappingProto::kJogFieldNumber, MIDIMappingProto::kJogBankFieldNumber,
85 delta_value, bind(&ControllerReceiver::jog, receiver, _1));
88 void MIDIMapper::note_on_received(int note)
90 lock_guard<mutex> lock(mu);
91 receiver->note_on(note);
93 if (mapping_proto->has_prev_bank() &&
94 mapping_proto->prev_bank().note_number() == note) {
95 current_controller_bank = (current_controller_bank + num_controller_banks - 1) % num_controller_banks;
96 update_lights_lock_held();
98 if (mapping_proto->has_next_bank() &&
99 mapping_proto->next_bank().note_number() == note) {
100 current_controller_bank = (current_controller_bank + 1) % num_controller_banks;
101 update_lights_lock_held();
103 if (mapping_proto->has_select_bank_1() &&
104 mapping_proto->select_bank_1().note_number() == note) {
105 current_controller_bank = 0;
106 update_lights_lock_held();
108 if (mapping_proto->has_select_bank_2() &&
109 mapping_proto->select_bank_2().note_number() == note &&
110 num_controller_banks >= 2) {
111 current_controller_bank = 1;
112 update_lights_lock_held();
114 if (mapping_proto->has_select_bank_3() &&
115 mapping_proto->select_bank_3().note_number() == note &&
116 num_controller_banks >= 3) {
117 current_controller_bank = 2;
118 update_lights_lock_held();
120 if (mapping_proto->has_select_bank_4() &&
121 mapping_proto->select_bank_4().note_number() == note &&
122 num_controller_banks >= 4) {
123 current_controller_bank = 3;
124 update_lights_lock_held();
126 if (mapping_proto->has_select_bank_5() &&
127 mapping_proto->select_bank_5().note_number() == note &&
128 num_controller_banks >= 5) {
129 current_controller_bank = 4;
130 update_lights_lock_held();
133 match_button(note, MIDIMappingProto::kPreviewFieldNumber, MIDIMappingProto::kPreviewBankFieldNumber,
134 bind(&ControllerReceiver::preview, receiver));
135 match_button(note, MIDIMappingProto::kQueueFieldNumber, MIDIMappingProto::kQueueBankFieldNumber,
136 bind(&ControllerReceiver::queue, receiver));
137 match_button(note, MIDIMappingProto::kPlayFieldNumber, MIDIMappingProto::kPlayBankFieldNumber,
138 bind(&ControllerReceiver::play, receiver));
140 unsigned num_cameras = std::min(MAX_STREAMS, mapping_proto->camera_size());
141 for (unsigned camera_idx = 0; camera_idx < num_cameras; ++camera_idx) {
142 const CameraMIDIMappingProto &camera = mapping_proto->camera(camera_idx);
143 if (match_bank_helper(camera, CameraMIDIMappingProto::kBankFieldNumber, current_controller_bank) &&
144 match_button_helper(camera, CameraMIDIMappingProto::kButtonFieldNumber, note)) {
145 receiver->switch_camera(camera_idx);
149 match_button(note, MIDIMappingProto::kCueInFieldNumber, MIDIMappingProto::kCueInBankFieldNumber,
150 bind(&ControllerReceiver::cue_in, receiver));
151 match_button(note, MIDIMappingProto::kCueOutFieldNumber, MIDIMappingProto::kCueOutBankFieldNumber,
152 bind(&ControllerReceiver::cue_out, receiver));
155 void MIDIMapper::match_controller(int controller, int field_number, int bank_field_number, float value, function<void(float)> func)
157 if (bank_mismatch(bank_field_number)) {
161 if (match_controller_helper(*mapping_proto, field_number, controller)) {
166 void MIDIMapper::match_button(int note, int field_number, int bank_field_number, function<void()> func)
168 if (bank_mismatch(bank_field_number)) {
172 if (match_button_helper(*mapping_proto, field_number, note)) {
177 bool MIDIMapper::has_active_controller(int field_number, int bank_field_number)
179 if (bank_mismatch(bank_field_number)) {
183 const FieldDescriptor *descriptor = mapping_proto->GetDescriptor()->FindFieldByNumber(field_number);
184 const Reflection *reflection = mapping_proto->GetReflection();
185 return reflection->HasField(*mapping_proto, descriptor);
188 bool MIDIMapper::bank_mismatch(int bank_field_number)
190 return !match_bank_helper(*mapping_proto, bank_field_number, current_controller_bank);
193 void MIDIMapper::refresh_lights()
195 lock_guard<mutex> lock(mu);
196 update_lights_lock_held();
199 void MIDIMapper::update_lights_lock_held()
201 set<unsigned> active_lights; // Desired state.
202 if (current_controller_bank == 0) {
203 activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank1IsSelectedFieldNumber, &active_lights);
205 if (current_controller_bank == 1) {
206 activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank2IsSelectedFieldNumber, &active_lights);
208 if (current_controller_bank == 2) {
209 activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank3IsSelectedFieldNumber, &active_lights);
211 if (current_controller_bank == 3) {
212 activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank4IsSelectedFieldNumber, &active_lights);
214 if (current_controller_bank == 4) {
215 activate_mapped_light(*mapping_proto, MIDIMappingProto::kBank5IsSelectedFieldNumber, &active_lights);
217 if (preview_enabled_light) {
218 activate_mapped_light(*mapping_proto, MIDIMappingProto::kPreviewEnabledFieldNumber, &active_lights);
220 if (queue_enabled_light) {
221 activate_mapped_light(*mapping_proto, MIDIMappingProto::kQueueEnabledFieldNumber, &active_lights);
223 if (play_enabled_light) {
224 activate_mapped_light(*mapping_proto, MIDIMappingProto::kPlayEnabledFieldNumber, &active_lights);
226 if (current_highlighted_camera >= 0 && current_highlighted_camera < mapping_proto->camera_size()) {
227 const CameraMIDIMappingProto &camera = mapping_proto->camera(current_highlighted_camera);
228 activate_mapped_light(camera, CameraMIDIMappingProto::kIsCurrentFieldNumber, &active_lights);
231 // These are always enabled right now.
232 activate_mapped_light(*mapping_proto, MIDIMappingProto::kCueInFieldNumber, &active_lights);
233 activate_mapped_light(*mapping_proto, MIDIMappingProto::kCueOutFieldNumber, &active_lights);
235 midi_device.update_lights(active_lights);