static int event_process_midi(snd_seq_event_t * ev, int direct, void *private_data, int atomic, int hop) { seq_midisynth_t *msynth = (seq_midisynth_t *) private_data; unsigned char msg[10]; /* buffer for constructing midi messages */ snd_rawmidi_substream_t *substream; int res; snd_assert(msynth != NULL, return -EINVAL); substream = msynth->output_rfile.output; if (substream == NULL) return -EINVAL; if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { /* invalid event */ snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); return 0; } res = snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); snd_midi_event_reset_decode(msynth->parser); if (res < 0) return res; } else { if (msynth->parser == NULL) return -EIO; res = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); if (res < 0) return res; if ((res = dump_midi(substream, msg, res)) < 0) { snd_midi_event_reset_decode(msynth->parser); return res; } } return 0; }
static int event_process_midi(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop) { struct seq_midisynth *msynth = private_data; unsigned char msg[10]; /* buffer for constructing midi messages */ struct snd_rawmidi_substream *substream; int len; if (snd_BUG_ON(!msynth)) return -EINVAL; substream = msynth->output_rfile.output; if (substream == NULL) return -ENODEV; if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { /* invalid event */ snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); return 0; } snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); snd_midi_event_reset_decode(msynth->parser); } else { if (msynth->parser == NULL) return -EIO; len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); if (len < 0) return 0; if (dump_midi(substream, msg, len) < 0) snd_midi_event_reset_decode(msynth->parser); } return 0; }
/* open associated midi device for output */ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info) { int err; struct seq_midisynth *msynth = private_data; struct snd_rawmidi_params params; /* open midi port */ if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) { snd_printd("midi output open failed!!!\n"); return err; } memset(¶ms, 0, sizeof(params)); params.avail_min = 1; params.buffer_size = output_buffer_size; params.no_active_sensing = 1; if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) { snd_rawmidi_kernel_release(&msynth->output_rfile); return err; } snd_midi_event_reset_decode(msynth->parser); return 0; }
static void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info) { jack_midi_data_t data[MAX_EVENT_SIZE]; stream_t *str = &self->stream[PORT_INPUT]; long size; int64_t alsa_time, time_offset; int64_t frame_offset, event_frame; port_t *port; port = port_get(str->ports, alsa_event->source); if (!port) return; /* * RPNs, NRPNs, Bank Change, etc. need special handling * but seems, ALSA does it for us already. */ snd_midi_event_reset_decode(str->codec); if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0) return; // fixup NoteOn with vel 0 if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) { data[0] = 0x80 + (data[0] & 0x0F); data[2] = 0x40; } alsa_time = alsa_event->time.time.tv_sec * NSEC_PER_SEC + alsa_event->time.time.tv_nsec; time_offset = info->alsa_time - alsa_time; frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC; event_frame = (int64_t)info->cur_frames - info->period_start - frame_offset + info->nframes; debug_log("input: %d bytes at event_frame = %d", (int)size, (int)event_frame); if (event_frame >= info->nframes && jack_ringbuffer_write_space(port->early_events) >= (sizeof(alsa_midi_event_t) + size)) { alsa_midi_event_t ev; ev.time = event_frame + info->period_start; ev.size = size; jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev)); jack_ringbuffer_write(port->early_events, (char*)data, size); debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes)); return; } if (event_frame < 0) event_frame = 0; else if (event_frame >= info->nframes) event_frame = info->nframes - 1; jack_midi_event_write(port->jack_buf, event_frame, data, size); }
void run() { const int maxEventSize = 16 * 1024; snd_midi_event_t* midiParser; if (snd_midi_event_new (maxEventSize, &midiParser) >= 0) { HeapBlock <uint8> buffer (maxEventSize); const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN); struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd)); snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN); while (! threadShouldExit()) { if (poll (pfd, numPfds, 500) > 0) { snd_seq_event_t* inputEvent = nullptr; snd_seq_nonblock (seqHandle, 1); do { if (snd_seq_event_input (seqHandle, &inputEvent) >= 0) { // xxx what about SYSEXes that are too big for the buffer? const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent); snd_midi_event_reset_decode (midiParser); if (numBytes > 0) { const MidiMessage message ((const uint8*) buffer, numBytes, Time::getMillisecondCounter() * 0.001); callback->handleIncomingMidiMessage (midiInput, message); } snd_seq_free_event (inputEvent); } } while (snd_seq_event_input_pending (seqHandle, 0) > 0); snd_seq_free_event (inputEvent); } } snd_midi_event_free (midiParser); } };
static int snd_rawmidi_virtual_drop(snd_rawmidi_t *rmidi) { snd_rawmidi_virtual_t *virt = rmidi->private_data; if (rmidi->stream == SND_RAWMIDI_STREAM_OUTPUT) { snd_seq_drop_output(virt->handle); snd_midi_event_reset_encode(virt->midi_event); virt->pending = 0; } else { snd_seq_drop_input(virt->handle); snd_midi_event_reset_decode(virt->midi_event); virt->in_buf_ofs = 0; } return 0; }
void Midi2UdpThread::run() { QUdpSocket *udpSocket; udpSocket = new QUdpSocket(0); forever { if (abort) { delete udpSocket; return; } if (poll(pfd, npfd, 250) > 0) { // Get MIDI event snd_seq_event_input(seq_handle, &midi_event); long len = snd_midi_event_decode(eventparser, midimsg, MAX_MIDI_MESSAGE_LENGTH, midi_event); if( len < 0 ) { printf("midi2udp: Error decoding midi event!\n"); } else { printf("midi2udp: got midi event: "); for(int i=0; i<len; ++i) { printf("0x%x ", midimsg[i]); } printf("\n"); // Send it over UDP for(set<string>::iterator ip_it = ds_ips.begin(); ip_it != ds_ips.end(); ++ip_it) { QString to_((*ip_it).c_str()); printf("sending to %s\n", (*ip_it).c_str()); QHostAddress to(to_); udpSocket->writeDatagram((char*)midimsg, len, to, DS_PORT); } } snd_seq_free_event(midi_event); snd_midi_event_reset_decode(eventparser); } } }
static void a2j_input_event (struct a2j * self, snd_seq_event_t * alsa_event) { jack_midi_data_t data[MAX_EVENT_SIZE]; struct a2j_stream *str = &self->stream; long size; struct a2j_port *port; jack_nframes_t now; now = jack_frame_time (self->jack_client); if ((port = a2j_port_get(str->port_hash, alsa_event->source)) == NULL) { return; } /* * RPNs, NRPNs, Bank Change, etc. need special handling * but seems, ALSA does it for us already. */ snd_midi_event_reset_decode(str->codec); if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0) { return; } // fixup NoteOn with vel 0 if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) { data[0] = 0x80 + (data[0] & 0x0F); data[2] = 0x40; } a2j_debug("input: %d bytes at event_frame=%u", (int)size, now); if (jack_ringbuffer_write_space(port->inbound_events) >= (sizeof(struct a2j_alsa_midi_event) + size)) { struct a2j_alsa_midi_event ev; char *ev_charp = (char*) &ev; size_t limit; size_t to_write = sizeof(ev); jack_ringbuffer_data_t vec[2]; jack_ringbuffer_get_write_vector( port->inbound_events, vec ); ev.time = now; ev.size = size; limit = (to_write > vec[0].len ? vec[0].len : to_write); if( limit ) { memcpy( vec[0].buf, ev_charp, limit ); to_write -= limit; ev_charp += limit; vec[0].buf += limit; vec[0].len -= limit; } if( to_write ) { memcpy( vec[1].buf, ev_charp, to_write ); vec[1].buf += to_write; vec[1].len -= to_write; } to_write = size; ev_charp = (char *)data; limit = (to_write > vec[0].len ? vec[0].len : to_write); if( limit ) memcpy( vec[0].buf, ev_charp, limit ); to_write -= limit; ev_charp += limit; if( to_write ) memcpy( vec[1].buf, ev_charp, to_write ); jack_ringbuffer_write_advance( port->inbound_events, sizeof(ev) + size ); } else { a2j_error ("MIDI data lost (incoming event buffer full): %ld bytes lost", size); } }
// alsa event capture. void samplv1_jack::alsa_capture ( snd_seq_event_t *ev ) { if (m_alsa_decoder == NULL) return; if (ev == NULL) return; // ignored events... switch(ev->type) { case SND_SEQ_EVENT_OSS: case SND_SEQ_EVENT_CLIENT_START: case SND_SEQ_EVENT_CLIENT_EXIT: case SND_SEQ_EVENT_CLIENT_CHANGE: case SND_SEQ_EVENT_PORT_START: case SND_SEQ_EVENT_PORT_EXIT: case SND_SEQ_EVENT_PORT_CHANGE: case SND_SEQ_EVENT_PORT_SUBSCRIBED: case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: case SND_SEQ_EVENT_USR0: case SND_SEQ_EVENT_USR1: case SND_SEQ_EVENT_USR2: case SND_SEQ_EVENT_USR3: case SND_SEQ_EVENT_USR4: case SND_SEQ_EVENT_USR5: case SND_SEQ_EVENT_USR6: case SND_SEQ_EVENT_USR7: case SND_SEQ_EVENT_USR8: case SND_SEQ_EVENT_USR9: case SND_SEQ_EVENT_BOUNCE: case SND_SEQ_EVENT_USR_VAR0: case SND_SEQ_EVENT_USR_VAR1: case SND_SEQ_EVENT_USR_VAR2: case SND_SEQ_EVENT_USR_VAR3: case SND_SEQ_EVENT_USR_VAR4: case SND_SEQ_EVENT_NONE: return; } #ifdef CONFIG_DEBUG_0 // - show (input) event for debug purposes... fprintf(stderr, "ALSA MIDI In: 0x%02x", ev->type); if (ev->type == SND_SEQ_EVENT_SYSEX) { fprintf(stderr, " SysEx {"); unsigned char *data = (unsigned char *) ev->data.ext.ptr; for (unsigned int i = 0; i < ev->data.ext.len; ++i) fprintf(stderr, " %02x", data[i]); fprintf(stderr, " }\n"); } else { for (unsigned int i = 0; i < sizeof(ev->data.raw8.d); ++i) fprintf(stderr, " %3d", ev->data.raw8.d[i]); fprintf(stderr, "\n"); } #endif const unsigned int nlimit = ::jack_ringbuffer_write_space(m_alsa_buffer); if (nlimit > sizeof(jack_midi_event_t) + 4) { unsigned char ev_buff[nlimit]; unsigned char *ev_data = &ev_buff[0] + sizeof(jack_midi_event_t); const int ev_size = snd_midi_event_decode(m_alsa_decoder, ev_data, nlimit - sizeof(jack_midi_event_t), ev); if (ev_size > 0) { jack_midi_event_t *ev_head = (jack_midi_event_t *) &ev_buff[0]; ev_head->time = ::jack_frame_time(m_client); ev_head->size = ev_size; ev_head->buffer = (jack_midi_data_t *) ev_data; ::jack_ringbuffer_write(m_alsa_buffer, (const char *) ev_buff, sizeof(jack_midi_event_t) + ev_size); } snd_midi_event_reset_decode(m_alsa_decoder); } }
/** * \brief Initializes MIDI parsers * \param dev MIDI event parser * \return 0 on success otherwise a negative error code * * Initializes MIDI parsers (both encode and decode) */ void snd_midi_event_init(snd_midi_event_t *dev) { snd_midi_event_reset_encode(dev); snd_midi_event_reset_decode(dev); }