]> git.sesse.net Git - nageru/blob - shared/midi_device.h
Support pitch bend as a virtual MIDI controller.
[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 <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         // Pitch bend events are received as a virtual controller with
20         // range -8192..8191 instead of 0..127 (but see the comment
21         // in map_controller_to_float() in midi_mapper.cpp).
22         static constexpr int PITCH_BEND_CONTROLLER = 128;
23
24         virtual ~MIDIReceiver() {}
25         virtual void controller_received(int controller, int value) = 0;
26         virtual void note_on_received(int note) = 0;
27         virtual void update_num_subscribers(unsigned num_subscribers) = 0;
28 };
29
30 class MIDIDevice {
31 public:
32         MIDIDevice(MIDIReceiver *receiver);
33         ~MIDIDevice();
34         void start_thread();
35
36         void update_lights(const std::set<unsigned> &active_lights)
37         {
38                 std::lock_guard<std::mutex> lock(mu);
39                 update_lights_lock_held(active_lights);
40         }
41
42 private:
43         void thread_func();
44         void handle_event(snd_seq_t *seq, snd_seq_event_t *event);
45         void subscribe_to_port_lock_held(snd_seq_t *seq, const snd_seq_addr_t &addr);
46         void update_lights_lock_held(const std::set<unsigned> &active_lights);
47
48         std::atomic<bool> should_quit{false};
49         int should_quit_fd;
50
51         mutable std::mutex mu;
52         MIDIReceiver *receiver;  // Under <mu>.
53
54         std::thread midi_thread;
55         std::map<unsigned, bool> current_light_status;  // Keyed by note number. Under <mu>.
56         snd_seq_t *alsa_seq{nullptr};  // Under <mu>.
57         int alsa_queue_id{-1};  // Under <mu>.
58         std::atomic<int> num_subscribed_ports{0};
59 };
60
61 #endif  // !defined(_MIDI_DEVICE_H)