summaryrefslogtreecommitdiffhomepage
path: root/MIDI.h
diff options
context:
space:
mode:
Diffstat (limited to 'MIDI.h')
-rw-r--r--MIDI.h169
1 files changed, 8 insertions, 161 deletions
diff --git a/MIDI.h b/MIDI.h
index e24c18a..177fd59 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -13,178 +13,25 @@
class MIDI
{
public:
- MIDI()
- {
- if (0 > snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK))
- {
- throw std::runtime_error("MIDI sequencer couldn't be opened");
- }
-
- if (0 > snd_seq_set_client_name(seq_handle, "Midi Listener"))
- {
- throw std::runtime_error("MIDI client name couldn't be set");
- }
-
- if (0 > ((in_port = snd_seq_create_simple_port(seq_handle, "24:0",
- SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
- SND_SEQ_PORT_TYPE_APPLICATION))))
- {
- throw std::runtime_error("MIDI port couldn't be opened");
- }
-
- debug_cout << "in_port: " << std::to_string(in_port) << std::endl;
-
-#if 1
- snd_seq_addr_t sender, dest;
- snd_seq_port_subscribe_t *subs;
- sender.client = 24;
- sender.port = 0;
- dest.client = snd_seq_client_id(seq_handle);
- dest.port = in_port;
- snd_seq_port_subscribe_alloca(&subs);
- snd_seq_port_subscribe_set_sender(subs, &sender);
- snd_seq_port_subscribe_set_dest(subs, &dest);
- snd_seq_port_subscribe_set_queue(subs, 1);
- snd_seq_port_subscribe_set_time_update(subs, 1);
- snd_seq_port_subscribe_set_time_real(subs, 1);
- // TODO: fix timestamp (currently always 0)
- if (0 > snd_seq_subscribe_port(seq_handle, subs))
-#endif
- //if (0 > snd_seq_connect_from(seq_handle, in_port, 24, 0))
- {
- throw std::runtime_error("MIDI port couldn't be connected");
- }
-
- npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
- if (npfd < 0) {
- throw std::runtime_error("snd_seq_poll_descriptors_count() failed");
- }
- pfd = (struct pollfd *)malloc(npfd * sizeof(struct pollfd));
- if (pfd == nullptr) {
- throw std::runtime_error("alloca() error for MIDI");
- }
- if (0 > snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN))
- {
- throw std::runtime_error("snd_seq_poll_descriptors() failure");
- }
-
- if (npfd != 1) {
- std::cout << "Warning: " << std::to_string(npfd) << " poll fds for MIDI" << std::endl;
- } else if (fd() <= 2) {
- std::cout << "Warning: Bad MIDI fd: " << std::to_string(fd()) << std::endl;
- }
- }
-
- ~MIDI()
- {
- free(pfd);
- }
+ MIDI();
+ ~MIDI();
boost::signals2::signal<void(int, int, uint64_t)> signal_note;
boost::signals2::signal<void()> signal_active_sensing;
boost::signals2::signal<void()> signal_clock;
- int fd()
- {
- return pfd->fd;
- }
-
- bool event_ready()
- {
- int result = snd_seq_event_input_pending(seq_handle, 1);
- if (result < 0) {
- throw std::runtime_error("snd_seq_event_input_pending() failed");
- }
-
- return result > 0;
- }
+ int fd();
- snd_seq_event_t *read(void)
- {
- snd_seq_event_t *ev = NULL;
- if (0 > snd_seq_event_input(seq_handle, &ev))
- {
- std::cerr << "snd_seq_event_input(): -EAGAIN" << std::endl;
- }
+ bool event_ready();
- return ev;
- }
-
- uint64_t timestamp_from_event(const snd_seq_event_t *ev)
- {
- return ((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_REAL) ? ev->time.time.tv_sec : ev->time.tick;
- }
+ snd_seq_event_t *read(void);
// returns if click starts
- void process(snd_seq_event_t *ev)
- {
- uint64_t timestamp = timestamp_from_event(ev); // original timestamp
-
- // TODO: fix timestamp to be set automatically
- struct timespec t;
- if (TIME_UTC != timespec_get(&t, TIME_UTC))
- {
- log_cout << "Error: timespec_get()" << std::endl;
- }
- else
- {
- ev->time.time.tv_sec = t.tv_sec;
- ev->time.time.tv_nsec = t.tv_nsec;
- }
-
- if ((ev->type == SND_SEQ_EVENT_NOTEON) ||(ev->type == SND_SEQ_EVENT_NOTEOFF)) {
- const char *type = (ev->type == SND_SEQ_EVENT_NOTEON) ? "on " : "off";
- debug_cout << fmt::format("[{}] Note {}: {:2x} vel({:2x}), ch {:2x}\n", timestamp,
- type,
- ev->data.note.note,
- ev->data.note.velocity,
- ev->data.control.channel);
- if (ev->type == SND_SEQ_EVENT_NOTEON) {
- signal_note(ev->data.control.channel, ev->data.note.note, timestamp);
- }
- }
- else if (ev->type == SND_SEQ_EVENT_CONTROLLER)
- {
- debug_cout << fmt::format("[{}] Control: {:2x} val({:2x})\n", timestamp_from_event(ev),
- ev->data.control.param,
- ev->data.control.value);
- }
- else if (ev->type == SND_SEQ_EVENT_SENSING)
- {
- signal_active_sensing();
- debug_cout << fmt::format("[{}] Active Sensing\n", timestamp_from_event(ev)) << std::endl;
- }
- else if (ev->type == SND_SEQ_EVENT_CLOCK)
- {
- signal_clock();
- debug_cout << fmt::format("[{}] Clock\n", timestamp_from_event(ev)) << std::endl;
- }
- else
- {
- log_cout << fmt::format("[{}] Unknown MIDI event: {}\n", timestamp_from_event(ev), ev->type) << std::endl;
- }
- }
+ void process(snd_seq_event_t *ev);
- void flush()
- {
- while (event_ready()) {
- (void) read();
- }
- }
+ void flush();
- void wait_for_event()
- {
- int result = poll(pfd, npfd, 10000);
- if (result > 0)
- {
- // event
- }
- else if (result == 0) {
- // timeout
- } else {
- throw std::runtime_error("Poll unsuccessful");
- }
- }
+ void wait_for_event();
private:
snd_seq_t *seq_handle;