2 #define _MIDI_MAPPER_H 1
4 // MIDIMapper in Futatabi is much the same as MIDIMapper in Nageru
5 // (it incoming MIDI messages from mixer controllers interprets them
6 // according to a user-defined mapping, and calls back into a receiver),
7 // and shares a fair amount of support code with it. However, it is
8 // also somewhat different; there are no audio buses, in particular.
9 // Also, DJ controllers typically have more buttons than audio controllers
10 // since there's only one (or maybe two) channels, so banks are less
11 // important, and thus, there's no highlighting. Also, the controllers
12 // are somewhat different, e.g., you have jog to deal with.
23 #include "shared/midi_device.h"
25 class MIDIMappingProto;
27 // Interface for receiving interpreted controller messages.
28 class ControllerReceiver {
30 virtual ~ControllerReceiver() {}
32 virtual void preview() = 0;
33 virtual void queue() = 0;
34 virtual void play() = 0;
35 virtual void jog(int delta) = 0;
36 virtual void switch_camera(unsigned camera_idx) = 0;
37 virtual void cue_in() = 0;
38 virtual void cue_out() = 0;
40 // Raw events; used for the editor dialog only.
41 virtual void controller_changed(unsigned controller) = 0;
42 virtual void note_on(unsigned note) = 0;
45 class MIDIMapper : public MIDIReceiver {
47 MIDIMapper(ControllerReceiver *receiver);
48 virtual ~MIDIMapper();
49 void set_midi_mapping(const MIDIMappingProto &new_mapping);
51 const MIDIMappingProto &get_current_mapping() const;
53 // Overwrites and returns the previous value.
54 ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
56 void refresh_lights();
58 void set_preview_enabled(bool enabled) {
59 preview_enabled_light = enabled;
62 void set_queue_enabled(bool enabled) {
63 queue_enabled_light = enabled;
66 void set_play_enabled(bool enabled) {
67 play_enabled_light = enabled;
70 void highlight_camera_input(int stream_idx) { // -1 for none.
71 current_highlighted_camera = stream_idx;
76 void controller_received(int controller, int value) override;
77 void note_on_received(int note) override;
78 void update_num_subscribers(unsigned num_subscribers) override {}
81 void match_controller(int controller, int field_number, int bank_field_number, float value, std::function<void(float)> func);
82 void match_button(int note, int field_number, int bank_field_number, std::function<void()> func);
83 bool has_active_controller(int field_number, int bank_field_number); // Also works for buttons.
84 bool bank_mismatch(int bank_field_number);
86 void update_lights_lock_held();
87 void activate_lights_all_buses(int field_number, std::set<unsigned> *active_lights);
89 std::atomic<bool> should_quit{false};
92 mutable std::mutex mu;
93 ControllerReceiver *receiver; // Under <mu>.
94 std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mu>.
95 int num_controller_banks; // Under <mu>.
96 std::atomic<int> current_controller_bank{0};
98 std::atomic<bool> preview_enabled_light{false};
99 std::atomic<bool> queue_enabled_light{false};
100 std::atomic<bool> play_enabled_light{false};
101 std::atomic<int> current_highlighted_camera{-1};
103 MIDIDevice midi_device;
106 bool load_midi_mapping_from_file(const std::string &filename, MIDIMappingProto *new_mapping);
107 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const std::string &filename);
109 #endif // !defined(_MIDI_MAPPER_H)