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 next() = 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 // Converts conveniently from a bool.
56 MIDIMapper(ControllerReceiver *receiver);
57 virtual ~MIDIMapper();
58 void set_midi_mapping(const MIDIMappingProto &new_mapping);
60 const MIDIMappingProto &get_current_mapping() const;
62 // Overwrites and returns the previous value.
63 ControllerReceiver *set_receiver(ControllerReceiver *new_receiver);
65 void refresh_lights();
67 void set_preview_enabled(LightState enabled) {
68 preview_enabled_light = enabled;
71 void set_queue_enabled(bool enabled) {
72 queue_enabled_light = enabled;
75 void set_play_enabled(LightState enabled) {
76 play_enabled_light = enabled;
79 void set_next_ready(LightState enabled) {
80 next_ready_light = enabled;
83 void set_locked(LightState locked) {
84 locked_light = locked;
87 void highlight_camera_input(int stream_idx) { // -1 for none.
88 current_highlighted_camera = stream_idx;
91 void set_speed_light(float speed) { // Goes from 0.0 to 2.0.
92 current_speed = speed;
97 void controller_received(int controller, int value) override;
98 void note_on_received(int note) override;
99 void update_num_subscribers(unsigned num_subscribers) override {}
102 void match_controller(int controller, int field_number, int bank_field_number, float value, std::function<void(float)> func);
103 void match_button(int note, int field_number, int bank_field_number, std::function<void()> func);
104 bool has_active_controller(int field_number, int bank_field_number); // Also works for buttons.
105 bool bank_mismatch(int bank_field_number);
107 void update_lights_lock_held();
109 std::atomic<bool> should_quit{false};
111 mutable std::mutex mu;
112 ControllerReceiver *receiver; // Under <mu>.
113 std::unique_ptr<MIDIMappingProto> mapping_proto; // Under <mu>.
114 int num_controller_banks; // Under <mu>.
115 std::atomic<int> current_controller_bank{0};
117 std::atomic<LightState> preview_enabled_light{Off};
118 std::atomic<bool> queue_enabled_light{false};
119 std::atomic<LightState> play_enabled_light{Off};
120 std::atomic<LightState> next_ready_light{Off};
121 std::atomic<LightState> locked_light{On};
122 std::atomic<int> current_highlighted_camera{-1};
123 std::atomic<float> current_speed{1.0f};
125 MIDIDevice midi_device;
128 bool load_midi_mapping_from_file(const std::string &filename, MIDIMappingProto *new_mapping);
129 bool save_midi_mapping_to_file(const MIDIMappingProto &mapping_proto, const std::string &filename);
131 #endif // !defined(_MIDI_MAPPER_H)