]> git.sesse.net Git - nageru/blob - nageru/midi_device.h
Small refactoring in MIDIMapper.
[nageru] / nageru / 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 <set>
11 #include <thread>
12
13 typedef struct snd_seq_addr snd_seq_addr_t;
14 typedef struct snd_seq_event snd_seq_event_t;
15 typedef struct _snd_seq snd_seq_t;
16
17 class MIDIReceiver {
18 public:
19         virtual ~MIDIReceiver() {}
20         virtual void controller_received(int controller, int value) = 0;
21         virtual void note_on_received(int note) = 0;
22         virtual void update_num_subscribers(unsigned num_subscribers) = 0;
23 };
24
25 class MIDIDevice {
26 public:
27         MIDIDevice(MIDIReceiver *receiver);
28         ~MIDIDevice();
29         void start_thread();
30
31         void update_lights(const std::set<unsigned> &active_lights)
32         {
33                 std::lock_guard<std::mutex> lock(mu);
34                 update_lights_lock_held(active_lights);
35         }
36
37 private:
38         void thread_func();
39         void handle_event(snd_seq_t *seq, snd_seq_event_t *event);
40         void subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_t &addr);
41         void update_lights_lock_held(const std::set<unsigned> &active_lights);
42
43         std::atomic<bool> should_quit{false};
44         int should_quit_fd;
45
46         mutable std::mutex mu;
47         MIDIReceiver *receiver;  // Under <mu>.
48
49         std::thread midi_thread;
50         std::map<unsigned, bool> current_light_status;  // Keyed by note number. Under <mu>.
51         snd_seq_t *alsa_seq{nullptr};  // Under <mu>.
52         int alsa_queue_id{-1};  // Under <mu>.
53         std::atomic<int> num_subscribed_ports{0};
54 };
55
56 #endif  // !defined(_MIDI_DEVICE_H)