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 set_master_speed(float speed) = 0;
38 virtual void cue_in() = 0;
39 virtual void cue_out() = 0;
41 // Raw events; used for the editor dialog only.
42 virtual void controller_changed(unsigned controller) = 0;
43 virtual void note_on(unsigned note) = 0;
46 class MIDIMapper : public MIDIReceiver {
48 MIDIMapper(ControllerReceiver *receiver);
49 virtual ~MIDIMapper();
50 void set_midi_mapping(const MIDIMappingProto &new_mapping);
52 const MIDIMappingProto &get_current_mapping() const;
54 // Overwrites and returns the previous value.
55 ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
57 void refresh_lights();
59 void set_preview_enabled(bool enabled) {
60 preview_enabled_light = enabled;
63 void set_queue_enabled(bool enabled) {
64 queue_enabled_light = enabled;
67 void set_play_enabled(bool enabled) {
68 play_enabled_light = enabled;
71 void highlight_camera_input(int stream_idx) { // -1 for none.
72 current_highlighted_camera = stream_idx;
77 void controller_received(int controller, int value) override;
78 void note_on_received(int note) override;
79 void update_num_subscribers(unsigned num_subscribers) override {}
82 void match_controller(int controller, int field_number, int bank_field_number, float value, std::function<void(float)> func);
83 void match_button(int note, int field_number, int bank_field_number, std::function<void()> func);
84 bool has_active_controller(int field_number, int bank_field_number); // Also works for buttons.
85 bool bank_mismatch(int bank_field_number);
87 void update_lights_lock_held();
88 void activate_lights_all_buses(int field_number, std::set<unsigned> *active_lights);
90 std::atomic<bool> should_quit{false};
93 mutable std::mutex mu;
94 ControllerReceiver *receiver; // Under <mu>.
95 std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mu>.
96 int num_controller_banks; // Under <mu>.
97 std::atomic<int> current_controller_bank{0};
99 std::atomic<bool> preview_enabled_light{false};
100 std::atomic<bool> queue_enabled_light{false};
101 std::atomic<bool> play_enabled_light{false};
102 std::atomic<int> current_highlighted_camera{-1};
104 MIDIDevice midi_device;
107 bool load_midi_mapping_from_file(const std::string &filename, MIDIMappingProto *new_mapping);
108 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const std::string &filename);
110 #endif // !defined(_MIDI_MAPPER_H)