static int midi_is_ready(process_midi_t *proc) { midi_port_t *port = proc->port; if (port->npfds) { unsigned short revents = 0; int res = snd_rawmidi_poll_descriptors_revents(port->rawmidi, proc->rpfds, port->npfds, &revents); if (res) { error_log("snd_rawmidi_poll_descriptors_revents failed on port %s with: %s", port->name, snd_strerror(res)); return 0; } if (revents & ~proc->mode) { debug_log("midi: port %s failed", port->name); return 0; } if (revents & proc->mode) { port->is_ready = 1; debug_log("midi: is_ready %s", port->name); } } return 1; }
gpointer read_data_thread(gboolean *stop) { /* This is mostly taken straight from alsa-utils-1.0.19 amidi/amidi.c by Clemens Ladisch <*****@*****.**> */ int err; int npfds; struct pollfd *pfds; GString *string = NULL; npfds = snd_rawmidi_poll_descriptors_count(input); pfds = alloca(npfds * sizeof(struct pollfd)); snd_rawmidi_poll_descriptors(input, pfds, npfds); do { unsigned char buf[256]; int i, length; unsigned short revents; /* SysEx messages can't contain bytes with 8th bit set. memset our buffer to 0xFF, so if for some reason we'll get out of reply bounds, we'll catch it */ memset(buf, '\0', sizeof(buf)); err = poll(pfds, npfds, 200); if (err < 0 && errno == EINTR) break; if (err < 0) { g_error("poll failed: %s", strerror(errno)); break; } if ((err = snd_rawmidi_poll_descriptors_revents(input, pfds, npfds, &revents)) < 0) { g_error("cannot get poll events: %s", snd_strerror(errno)); break; } if (revents & (POLLERR | POLLHUP)) break; if (!(revents & POLLIN)) continue; err = snd_rawmidi_read(input, buf, sizeof(buf)); if (err == -EAGAIN) continue; if (err < 0) { g_error("cannot read: %s", snd_strerror(err)); break; } length = 0; for (i = 0; i < err; ++i) if ((unsigned char)buf[i] != 0xFE) /* ignore active sensing */ buf[length++] = buf[i]; i = 0; while (i < length) { int pos; int bytes; if (string == NULL) { while (buf[i] != 0xF0 && i < length) i++; } pos = i; for (bytes = 0; (bytes<length-i) && (buf[i+bytes] != 0xF7); bytes++); if (buf[i+bytes] == 0xF7) bytes++; i += bytes; if (string == NULL) string = g_string_new_len((gchar*)&buf[pos], bytes); else g_string_append_len(string, (gchar*)&buf[pos], bytes); if ((unsigned char)string->str[string->len-1] == 0xF7) { /* push message on stack */ push_message(string); string = NULL; } } } while (*stop == FALSE); if (string) { g_string_free(string, TRUE); string = NULL; } return NULL; }
void MidiAlsaRaw::run() { unsigned char buf[128]; //int cnt = 0; while( m_quit == false ) { msleep( 5 ); // must do that, otherwise this thread takes // too much CPU-time, even with LowPriority... int err = poll( m_pfds, m_npfds, 10000 ); if( err < 0 && errno == EINTR ) { printf( "MidiAlsaRaw::run(): Got EINTR while " "polling. Will stop polling MIDI-events from " "MIDI-port.\n" ); break; } if( err < 0 ) { printf( "poll failed: %s\nWill stop polling " "MIDI-events from MIDI-port.\n", strerror( errno ) ); break; } if( err == 0 ) { //printf( "there seems to be no active MIDI-device %d\n", ++cnt ); continue; } unsigned short revents; if( ( err = snd_rawmidi_poll_descriptors_revents( m_input, m_pfds, m_npfds, &revents ) ) < 0 ) { printf( "cannot get poll events: %s\nWill stop polling " "MIDI-events from MIDI-port.\n", snd_strerror( errno ) ); break; } if( revents & ( POLLERR | POLLHUP ) ) { printf( "POLLERR or POLLHUP\n" ); break; } if( !( revents & POLLIN ) ) { continue; } err = snd_rawmidi_read( m_input, buf, sizeof( buf ) ); if( err == -EAGAIN ) { continue; } if( err < 0 ) { printf( "cannot read from port \"%s\": %s\nWill stop " "polling MIDI-events from MIDI-port.\n", /*port_name*/"default", snd_strerror( err ) ); break; } if( err == 0 ) { continue; } for( int i = 0; i < err; ++i ) { parseData( buf[i] ); } } }