static int osc_midi ( DssiEditor *pDssiEditor, lo_arg **argv ) { static snd_midi_event_t *s_pAlsaCoder = NULL; static snd_seq_event_t s_aAlsaEvent[4]; const unsigned char *data = argv[0]->m; #ifdef CONFIG_DEBUG qDebug("osc_midi: path \"%s\", midi 0x%02x 0x%02x 0x%02x 0x%02x", pDssiEditor->path, data[0], data[1], data[2], data[3]); #endif qtractorDssiPlugin *pDssiPlugin = pDssiEditor->plugin; if (pDssiPlugin == NULL) return 1; qtractorMidiManager *pMidiManager = (pDssiPlugin->list())->midiManager(); if (pMidiManager == NULL) return 1; if (s_pAlsaCoder == NULL && snd_midi_event_new(4, &s_pAlsaCoder)) return 1; snd_midi_event_reset_encode(s_pAlsaCoder); if (snd_midi_event_encode(s_pAlsaCoder, &data[1], 3, s_aAlsaEvent) < 1) return 1; // Send the event directly to snd_seq_event_t *pEvent = &s_aAlsaEvent[0]; if (snd_seq_ev_is_channel_type(pEvent)) pMidiManager->direct(pEvent); return 0; }
void DssiPluginMidiManager::convertMidiMessages (MidiBuffer& midiMessages, const int blockSamples) { const uint8* data; int numBytesOfMidiData, samplePosition; MidiBuffer::Iterator it (midiMessages); currentMidiCount = 0; while (it.getNextEvent (data, numBytesOfMidiData, samplePosition)) { if (numBytesOfMidiData > maxEventSize) { maxEventSize = numBytesOfMidiData; snd_midi_event_free (midiParser); snd_midi_event_new (maxEventSize, &midiParser); } snd_seq_event_t* event = & midiEventsBuffer [currentMidiCount]; snd_seq_ev_clear (event); snd_midi_event_encode (midiParser, data, numBytesOfMidiData, event); if (++currentMidiCount >= 2048) break; } snd_midi_event_reset_encode (midiParser); }
void midibus::play (event * a_e24, unsigned char a_channel) { #ifdef HAVE_LIBASOUND automutex locker(m_mutex); snd_seq_event_t ev; snd_midi_event_t *midi_ev; /* ALSA MIDI parser */ unsigned char buffer[3]; /* temp for MIDI data */ /* fill buffer and set midi channel */ buffer[0] = a_e24->get_status(); buffer[0] += (a_channel & 0x0F); a_e24->get_data(&buffer[1], &buffer[2]); snd_midi_event_new(10, &midi_ev); /* clear event */ snd_seq_ev_clear(&ev); snd_midi_event_encode(midi_ev, buffer, 3, &ev); snd_midi_event_free(midi_ev); /* set source */ snd_seq_ev_set_source(&ev, m_local_addr_port); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); // its immediate /* pump it into the queue */ snd_seq_event_output(m_seq, &ev); #endif // HAVE_LIBASOUND }
void sendMessageNow (const MidiMessage& message) { if (message.getRawDataSize() > maxEventSize) { maxEventSize = message.getRawDataSize(); snd_midi_event_free (midiParser); snd_midi_event_new (maxEventSize, &midiParser); } snd_seq_event_t event; snd_seq_ev_clear (&event); long numBytes = (long) message.getRawDataSize(); const uint8* data = message.getRawData(); while (numBytes > 0) { const long numSent = snd_midi_event_encode (midiParser, data, numBytes, &event); if (numSent <= 0) break; numBytes -= numSent; data += numSent; snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_subs (&event); snd_seq_ev_set_direct (&event); snd_seq_event_output (seqHandle, &event); } snd_seq_drain_output (seqHandle); snd_midi_event_reset_encode (midiParser); }
void sendMessageNow (const MidiMessage& message) { if (message.getRawDataSize() > maxEventSize) { maxEventSize = message.getRawDataSize(); snd_midi_event_free (midiParser); snd_midi_event_new (maxEventSize, &midiParser); } snd_seq_event_t event; snd_seq_ev_clear (&event); snd_midi_event_encode (midiParser, message.getRawData(), message.getRawDataSize(), &event); snd_midi_event_reset_encode (midiParser); snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_subs (&event); snd_seq_ev_set_direct (&event); snd_seq_event_output (seqHandle, &event); snd_seq_drain_output (seqHandle); }
static void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info) { stream_t *str = &self->stream[info->dir]; int nevents = jack_midi_get_event_count(port->jack_buf); int i; for (i=0; i<nevents; ++i) { jack_midi_event_t jack_event; snd_seq_event_t alsa_event; int64_t frame_offset; int64_t out_time; snd_seq_real_time_t out_rt; int err; jack_midi_event_get(&jack_event, port->jack_buf, i); snd_seq_ev_clear(&alsa_event); snd_midi_event_reset_encode(str->codec); if (!snd_midi_event_encode(str->codec, jack_event.buffer, jack_event.size, &alsa_event)) continue; // invalid event snd_seq_ev_set_source(&alsa_event, self->port_id); snd_seq_ev_set_dest(&alsa_event, port->remote.client, port->remote.port); /* NOTE: in case of xrun it could become negative, so it is essential to use signed type! */ frame_offset = (int64_t)jack_event.time + info->period_start + info->nframes - info->cur_frames; if (frame_offset < 0) { frame_offset = info->nframes + jack_event.time; error_log("internal xrun detected: frame_offset = %"PRId64"\n", frame_offset); } /* Ken Ellinwood reported problems with this assert. * Seems, magic 2 should be replaced with nperiods. */ //FIXME: assert (frame_offset < info->nframes*2); //if (frame_offset < info->nframes * info->nperiods) // debug_log("alsa_out: BLAH-BLAH-BLAH"); out_time = info->alsa_time + (frame_offset * NSEC_PER_SEC) / info->sample_rate; debug_log("alsa_out: frame_offset = %lld, info->alsa_time = %lld, out_time = %lld, port->last_out_time = %lld", frame_offset, info->alsa_time, out_time, port->last_out_time); // we should use absolute time to prevent reordering caused by rounding errors if (out_time < port->last_out_time) { debug_log("alsa_out: limiting out_time %lld at %lld", out_time, port->last_out_time); out_time = port->last_out_time; } else port->last_out_time = out_time; out_rt.tv_nsec = out_time % NSEC_PER_SEC; out_rt.tv_sec = out_time / NSEC_PER_SEC; snd_seq_ev_schedule_real(&alsa_event, self->queue, 0, &out_rt); err = snd_seq_event_output(self->seq, &alsa_event); debug_log("alsa_out: written %d bytes to %s at %+d (%lld): %d", (int)jack_event.size, port->name, (int)frame_offset, out_time, err); } }
/* takes an native event, encodes to alsa event, puts it in the queue */ void midibus::play( event *a_e24, unsigned char a_channel ) { lock(); snd_seq_event_t ev; /* alsa midi parser */ snd_midi_event_t *midi_ev; /* temp for midi data */ unsigned char buffer[3]; /* fill buffer and set midi channel */ buffer[0] = a_e24->get_status(); buffer[0] += (a_channel & 0x0F); a_e24->get_data( &buffer[1], &buffer[2] ); snd_midi_event_new( 10, &midi_ev ); /* clear event */ snd_seq_ev_clear( &ev ); snd_midi_event_encode( midi_ev, buffer, 3, &ev ); snd_midi_event_free( midi_ev ); /* set source */ snd_seq_ev_set_source(&ev, m_local_addr_port ); snd_seq_ev_set_subs(&ev); /* set tag unique to each sequence for removal purposes */ //ev.tag = a_tag; // its immediate snd_seq_ev_set_direct( &ev ); /* pump it into the queue */ snd_seq_event_output(m_seq, &ev); unlock(); }
void midi_send(uint32 data) { snd_seq_event_t ev; if (s_midi == NULL) return; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, s_midiPort); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); snd_midi_event_encode(s_midiCoder, (uint8 *)&data, sizeof(uint32), &ev); snd_seq_event_output(s_midi, &ev); snd_seq_drain_output(s_midi); }
bool sendMessageNow (const MidiMessage& message) { if (message.getRawDataSize() > maxEventSize) { maxEventSize = message.getRawDataSize(); snd_midi_event_free (midiParser); snd_midi_event_new ((size_t) maxEventSize, &midiParser); } snd_seq_event_t event; snd_seq_ev_clear (&event); long numBytes = (long) message.getRawDataSize(); const uint8* data = message.getRawData(); snd_seq_t* seqHandle = port.client->get(); bool success = true; while (numBytes > 0) { const long numSent = snd_midi_event_encode (midiParser, data, numBytes, &event); if (numSent <= 0) { success = numSent == 0; break; } numBytes -= numSent; data += numSent; snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_subs (&event); snd_seq_ev_set_direct (&event); if (snd_seq_event_output_direct (seqHandle, &event) < 0) { success = false; break; } } snd_midi_event_reset_encode (midiParser); return success; }
static ssize_t snd_rawmidi_virtual_write(snd_rawmidi_t *rmidi, const void *buffer, size_t size) { snd_rawmidi_virtual_t *virt = rmidi->private_data; ssize_t result = 0; ssize_t size1; int err; if (virt->pending) { err = snd_seq_event_output(virt->handle, &virt->out_event); if (err < 0) { if (err != -EAGAIN) /* we got some fatal error. removing this event * at the next time */ virt->pending = 0; return err; } virt->pending = 0; } while (size > 0) { size1 = snd_midi_event_encode(virt->midi_event, buffer, size, &virt->out_event); if (size1 <= 0) break; size -= size1; result += size1; buffer += size1; if (virt->out_event.type == SND_SEQ_EVENT_NONE) continue; snd_seq_ev_set_subs(&virt->out_event); snd_seq_ev_set_source(&virt->out_event, virt->port); snd_seq_ev_set_direct(&virt->out_event); err = snd_seq_event_output(virt->handle, &virt->out_event); if (err < 0) { virt->pending = 1; return result > 0 ? result : err; } } if (result > 0) snd_seq_drain_output(virt->handle); return result; }
/* handle rawmidi input event (MIDI v1.0 stream) */ static void snd_midi_input_event(snd_rawmidi_substream_t * substream) { snd_rawmidi_runtime_t *runtime; seq_midisynth_t *msynth; snd_seq_event_t ev; char buf[16], *pbuf; long res, count; if (substream == NULL) return; runtime = substream->runtime; msynth = (seq_midisynth_t *) runtime->private_data; if (msynth == NULL) return; memset(&ev, 0, sizeof(ev)); while (runtime->avail > 0) { res = snd_rawmidi_kernel_read(substream, buf, sizeof(buf)); if (res <= 0) continue; if (msynth->parser == NULL) continue; pbuf = buf; while (res > 0) { count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev); if (count < 0) break; pbuf += count; res -= count; if (ev.type != SNDRV_SEQ_EVENT_NONE) { ev.source.port = msynth->seq_port; ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); /* clear event and reset header */ memset(&ev, 0, sizeof(ev)); } } } }
void midibus::play (event * e24, midibyte channel) { #ifdef SEQ64_HAVE_LIBASOUND automutex locker(m_mutex); midibyte buffer[4]; /* temp for MIDI data */ buffer[0] = e24->get_status(); /* fill buffer */ buffer[0] += (channel & 0x0F); e24->get_data(buffer[1], buffer[2]); /* set MIDI data */ snd_midi_event_t * midi_ev; /* ALSA MIDI parser */ snd_midi_event_new(SEQ64_MIDI_EVENT_SIZE_MAX, &midi_ev); snd_seq_event_t ev; snd_seq_ev_clear(&ev); /* clear event */ snd_midi_event_encode(midi_ev, buffer, 3, &ev); /* encode 3 raw bytes */ snd_midi_event_free(midi_ev); /* free the parser */ snd_seq_ev_set_source(&ev, m_local_addr_port); /* set source */ snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); /* it is immediate */ snd_seq_event_output(m_seq, &ev); /* pump into the queue */ #endif // SEQ64_HAVE_LIBASOUND }
void QMidi::outSendMsg(qint32 msg) { #if defined(Q_OS_WIN) midiOutShortMsg(midiOutPtr,(DWORD)msg); #elif defined(Q_OS_LINUX) snd_seq_event_t ev; snd_midi_event_t* mev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, 0); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); snd_midi_event_new(sizeof(msg), &mev); snd_midi_event_resize_buffer(mev, sizeof(msg)); snd_midi_event_encode(mev,(unsigned char*)&msg, sizeof(msg), &ev); snd_seq_event_output(midiOutPtr, &ev); snd_seq_drain_output(midiOutPtr); #elif defined(Q_OS_HAIKU) midiOutLocProd->SprayData((void*)&msg,sizeof(msg),true); #endif }
void Alsa::sendMessage(const std::vector<uint8_t> *msg_ ) { int result; unsigned int nBytes = msg_->size(); if ( nBytes > _apiData->bufferSize ) { _apiData->bufferSize = nBytes; result = snd_midi_event_resize_buffer ( _apiData->coder, nBytes); if ( result != 0 ) { std::cerr << "error: CxxMidi::Output::Alsa::sendMessage: ALSA error resizing MIDI event buffer" << std::endl; } free (_apiData->buffer); _apiData->buffer = (unsigned char *) malloc( _apiData->bufferSize ); if ( _apiData->buffer == NULL ) { std::cerr << "error: CxxMidi::Output::Alsa::sendMessage: error allocating buffer memory" << std::endl; } } snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, _apiData->vport); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); for ( unsigned int i=0; i<nBytes; ++i ) _apiData->buffer[i] = msg_->at(i); result = snd_midi_event_encode( _apiData->coder, _apiData->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { std::cerr << "error: CxxMidi::Output::Alsa::sendMessage: event parsing error" << std::endl; return; } // Send the event. result = snd_seq_event_output(_apiData->seq, &ev); if ( result < 0 ) { std::cerr << "error: CxxMidi::Output::Alsa::sendMessage: error sending MIDI message to port" << std::endl; } snd_seq_drain_output(_apiData->seq); }
void Udp2MidiThread::run() { QUdpSocket *udpSocket = new QUdpSocket(); bool bres = udpSocket->bind(PC_PORT); if( bres == false ) { printf("Could not bind to port %d!\n", PC_PORT); return; } forever { if (abort) { delete udpSocket; return; } if( udpSocket->waitForReadyRead(250) == true ) { // Receive from UDP QHostAddress from_address; int len = udpSocket->readDatagram((char*)midimsg, MAX_MIDI_MESSAGE_LENGTH, &from_address); if( len == -1 ) { printf("udp2midi: Error receiving data!\n"); } if( (len == 3) && (midimsg[0] == 0) && (midimsg[1] == 0) && (midimsg[2] == 0) ) { string from_ip = from_address.toString().toStdString(); printf("Keepalive from: %s\n", from_ip.c_str()); midi2udp->add_ip(from_ip); } else { // Send to MIDI printf("udp2midi: Sending event: "); for(int i=0; i<len; ++i) { printf("0x%x ", midimsg[i]); } printf("\n"); long res = snd_midi_event_encode(eventparser, midimsg, len, midi_event); if( res < 0) { printf("Error encoding midi event!\n"); } snd_midi_event_reset_encode(eventparser); if(midi_event->type == SND_SEQ_EVENT_NOTEON) { printf("udp2midi: Note on: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } else if(midi_event->type == SND_SEQ_EVENT_NOTEOFF){ printf("udp2midi: Note off: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } snd_seq_ev_set_subs(midi_event); snd_seq_ev_set_direct(midi_event); snd_seq_ev_set_source(midi_event, midi_out_port); snd_seq_event_output_direct(seq_handle, midi_event); snd_seq_free_event(midi_event); } } } }