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.
22 #include "shared/midi_device.h"
24 class MIDIMappingProto;
26 // Interface for receiving interpreted controller messages.
27 class ControllerReceiver {
29 virtual ~ControllerReceiver() {}
31 virtual void preview() = 0;
32 virtual void queue() = 0;
33 virtual void play() = 0;
34 virtual void toggle_lock() = 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 // Converts conveniently from a bool.
55 MIDIMapper(ControllerReceiver *receiver);
56 virtual ~MIDIMapper();
57 void set_midi_mapping(const MIDIMappingProto &new_mapping);
59 const MIDIMappingProto &get_current_mapping() const;
61 // Overwrites and returns the previous value.
62 ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
64 void refresh_lights();
66 void set_preview_enabled(LightState enabled) {
67 preview_enabled_light = enabled;
70 void set_queue_enabled(bool enabled) {
71 queue_enabled_light = enabled;
74 void set_play_enabled(LightState enabled) {
75 play_enabled_light = enabled;
78 void set_locked(LightState locked) {
79 locked_light = locked;
82 void highlight_camera_input(int stream_idx) { // -1 for none.
83 current_highlighted_camera = stream_idx;
86 void set_speed_light(float speed) { // Goes from 0.0 to 2.0.
87 current_speed = speed;
92 void controller_received(int controller, int value) override;
93 void note_on_received(int note) override;
94 void update_num_subscribers(unsigned num_subscribers) override {}
97 void match_controller(int controller, int field_number, int bank_field_number, float value, std::function<void(float)> func);
98 void match_button(int note, int field_number, int bank_field_number, std::function<void()> func);
99 bool has_active_controller(int field_number, int bank_field_number); // Also works for buttons.
100 bool bank_mismatch(int bank_field_number);
102 void update_lights_lock_held();
104 std::atomic<bool> should_quit{false};
106 mutable std::mutex mu;
107 ControllerReceiver *receiver; // Under <mu>.
108 std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mu>.
109 int num_controller_banks; // Under <mu>.
110 std::atomic<int> current_controller_bank{0};
112 std::atomic<LightState> preview_enabled_light{Off};
113 std::atomic<bool> queue_enabled_light{false};
114 std::atomic<LightState> play_enabled_light{Off};
115 std::atomic<LightState> locked_light{On};
116 std::atomic<int> current_highlighted_camera{-1};
117 std::atomic<float> current_speed{1.0f};
119 MIDIDevice midi_device;
122 bool load_midi_mapping_from_file(const std::string &filename, MIDIMappingProto *new_mapping);
123 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const std::string &filename);
125 #endif // !defined(_MIDI_MAPPER_H)