diff options
Diffstat (limited to 'MIDI.h')
-rw-r--r-- | MIDI.h | 169 |
1 files changed, 8 insertions, 161 deletions
@@ -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; |