]> git.sesse.net Git - nageru/blob - shared/midi_device.h
9c76d18b9d1a667c18cf2111f9fc36d4ac63ee80
[nageru] / shared / midi_device.h
1 #ifndef _MIDI_DEVICE_H
2 #define _MIDI_DEVICE_H 1
3
4 // MIDIDevice is a class that pools incoming MIDI messages from
5 // all MIDI devices in the system, decodes them and sends them on.
6
7 #include <atomic>
8 #include <map>
9 #include <mutex>
10 #include <thread>
11
12 typedef struct snd_seq_addr snd_seq_addr_t;
13 typedef struct snd_seq_event snd_seq_event_t;
14 typedef struct _snd_seq snd_seq_t;
15
16 class MIDIReceiver {
17 public:
18         // Pitch bend events are received as a virtual controller with
19         // range -8192..8191 instead of 0..127 (but see the comment
20         // in map_controller_to_float() in midi_mapper.cpp).
21         static constexpr int PITCH_BEND_CONTROLLER = 128;
22
23         virtual ~MIDIReceiver() {}
24         virtual void controller_received(int controller, int value) = 0;
25         virtual void note_on_received(int note) = 0;
26         virtual void update_num_subscribers(unsigned num_subscribers) = 0;
27 };
28
29 class MIDIDevice {
30 public:
31         MIDIDevice(MIDIReceiver *receiver);
32         ~MIDIDevice();
33         void start_thread();
34
35         void update_lights(const std::map<unsigned, uint8_t> &active_lights)
36         {
37                 std::lock_guard<std::mutex> lock(mu);
38                 update_lights_lock_held(active_lights);
39         }
40
41 private:
42         void thread_func();
43         void handle_event(snd_seq_t *seq, snd_seq_event_t *event);
44         void subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_t &addr);
45         void update_lights_lock_held(const std::map<unsigned, uint8_t> &active_lights);
46
47         std::atomic<bool> should_quit{false};
48         int should_quit_fd;
49
50         mutable std::mutex mu;
51         MIDIReceiver *receiver;  // Under <mu>.
52
53         std::thread midi_thread;
54         std::map<unsigned, uint8_t> current_light_status;  // Keyed by note number. Under <mu>.
55         snd_seq_t *alsa_seq{nullptr};  // Under <mu>.
56         int alsa_queue_id{-1};  // Under <mu>.
57         std::atomic<int> num_subscribed_ports{0};
58 };
59
60 #endif  // !defined(_MIDI_DEVICE_H)