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 toggle_lock() = 0;
36 virtual void jog(int delta) = 0;
37 virtual void switch_camera(unsigned camera_idx) = 0;
38 virtual void set_master_speed(float speed) = 0;
39 virtual void cue_in() = 0;
40 virtual void cue_out() = 0;
42 // Raw events; used for the editor dialog only.
43 virtual void controller_changed(unsigned controller) = 0;
44 virtual void note_on(unsigned note) = 0;
47 class MIDIMapper : public MIDIReceiver {
49 MIDIMapper(ControllerReceiver *receiver);
50 virtual ~MIDIMapper();
51 void set_midi_mapping(const MIDIMappingProto &new_mapping);
53 const MIDIMappingProto &get_current_mapping() const;
55 // Overwrites and returns the previous value.
56 ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
58 void refresh_lights();
60 void set_preview_enabled(bool enabled) {
61 preview_enabled_light = enabled;
64 void set_queue_enabled(bool enabled) {
65 queue_enabled_light = enabled;
68 void set_play_enabled(bool enabled) {
69 play_enabled_light = enabled;
72 void set_locked(bool locked) {
73 locked_light = locked;
76 void highlight_camera_input(int stream_idx) { // -1 for none.
77 current_highlighted_camera = stream_idx;
82 void controller_received(int controller, int value) override;
83 void note_on_received(int note) override;
84 void update_num_subscribers(unsigned num_subscribers) override {}
87 void match_controller(int controller, int field_number, int bank_field_number, float value, std::function<void(float)> func);
88 void match_button(int note, int field_number, int bank_field_number, std::function<void()> func);
89 bool has_active_controller(int field_number, int bank_field_number); // Also works for buttons.
90 bool bank_mismatch(int bank_field_number);
92 void update_lights_lock_held();
93 void activate_lights_all_buses(int field_number, std::set<unsigned> *active_lights);
95 std::atomic<bool> should_quit{false};
98 mutable std::mutex mu;
99 ControllerReceiver *receiver; // Under <mu>.
100 std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mu>.
101 int num_controller_banks; // Under <mu>.
102 std::atomic<int> current_controller_bank{0};
104 std::atomic<bool> preview_enabled_light{false};
105 std::atomic<bool> queue_enabled_light{false};
106 std::atomic<bool> play_enabled_light{false};
107 std::atomic<bool> locked_light{true};
108 std::atomic<int> current_highlighted_camera{-1};
110 MIDIDevice midi_device;
113 bool load_midi_mapping_from_file(const std::string &filename, MIDIMappingProto *new_mapping);
114 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const std::string &filename);
116 #endif // !defined(_MIDI_MAPPER_H)