static void do_jack_output(process_jack_t *proc) { output_port_t *port = (output_port_t*) proc->port; int nevents = jack_midi_get_event_count(proc->buffer); int i; if (nevents) debug_log("jack_out: %d events in %s", nevents, port->base.name); for (i=0; i<nevents; ++i) { jack_midi_event_t event; event_head_t hdr; jack_midi_event_get(&event, proc->buffer, i); if (jack_ringbuffer_write_space(port->base.data_ring) < event.size || jack_ringbuffer_write_space(port->base.event_ring) < sizeof(hdr)) { debug_log("jack_out: output buffer overflow on %s", port->base.name); break; } midi_pack_event(&port->packer, &event); jack_ringbuffer_write(port->base.data_ring, (char*)event.buffer, event.size); hdr.time = proc->frame_time + event.time + proc->nframes; hdr.size = event.size; jack_ringbuffer_write(port->base.event_ring, (char*)&hdr, sizeof(hdr)); debug_log("jack_out: sent %d-byte event at %ld", (int)event.size, (long)event.time); } }
int process (jack_nframes_t frames, void* arg) { void* buffer; jack_nframes_t N; jack_nframes_t i; char description[256]; buffer = jack_port_get_buffer (port, frames); assert (buffer); N = jack_midi_get_event_count (buffer); for (i = 0; i < N; ++i) { jack_midi_event_t event; int r; r = jack_midi_event_get (&event, buffer, i); if (r == 0) { size_t j; printf ("%d:", event.time); for (j = 0; j < event.size; ++j) { printf (" %x", event.buffer[j]); } describe (&event, description, sizeof (description)); printf (" %s", description); printf ("\n"); } } return 0; }
PRIVATE void midiinport_realtime_handler(Generator *g, AEvent *event) { MidiInData *data = g->data; jack_nframes_t nframes = event->d.integer; void * input_buf; jack_midi_event_t input_event; jack_nframes_t input_event_count; jack_nframes_t i; unsigned char * data; input_buf = jack_port_get_buffer(data->port, nframes); input_event_count = jack_midi_get_event_count(input_buf, nframes); /* iterate over all incoming JACK MIDI events */ for (i = 0; i < input_event_count; i++) { /* retrieve JACK MIDI event */ jack_midi_event_get(&input_event, input_buf, i, nframes); event->time = input_event.time + gen_get_sampletime(); event->type = AE_MIDIEVENT; event->midiev.len = input_event.size; memcpy( &(event->midiev.midistring), input_event.buffer, input_event.size); /* normalise note events if needed */ if ((input_event.size == 3) && ((event->midiev[0] & 0xF0) == 0x90) && (event->midiev[2] == 0)) { event->midiev[0] = 0x80 | (event->midiev[0] & 0x0F); } gen_send_events(g, EVT_MIDIEVT, -1, &e); } }
int jack_audio_callback(jack_nframes_t nframes, void *arg) { int c,s; WfAudioInfo* nfo = &myplayer->info; #ifdef JACK_MIDI int n; void *jack_buf = jack_port_get_buffer(jack_midi_port, nframes); int nevents = jack_midi_get_event_count(jack_buf); for (n=0; n<nevents; n++) { jack_midi_event_t ev; jack_midi_event_get(&ev, jack_buf, n); if (ev.size < 3 || ev.size > 3) continue; // filter note on/off else { event_queue[queued_events_end].time = ev.time; event_queue[queued_events_end].size = ev.size; memcpy (event_queue[queued_events_end].buffer, ev.buffer, ev.size); queued_events_end = (queued_events_end +1 ) % JACK_MIDI_QUEUE_SIZE; } } if (queued_events_start != queued_events_end) { /* Tell the midi thread there is work to do. */ if(pthread_mutex_trylock(&midi_thread_lock) == 0) { pthread_cond_signal(&midi_ready); pthread_mutex_unlock(&midi_thread_lock); } } #endif if (!player_active) return (0); for(c=0; c<nfo->channels; c++) { j_out[c] = (jack_default_audio_sample_t*) jack_port_get_buffer(j_output_port[c], nframes); } if(playpause || jack_ringbuffer_read_space(rb) < nfo->channels * nframes * sizeof(jack_default_audio_sample_t)) { silent = 1; for(c=0; c< nfo->channels; c++) { memset(j_out[c], 0, nframes * sizeof(jack_default_audio_sample_t)); } } else { silent=0; /* de-interleave */ for(s=0; s<nframes; s++) { for(c=0; c< nfo->channels; c++) { jack_ringbuffer_read(rb, (char*) &j_out[c][s], sizeof(jack_default_audio_sample_t)); } } } /* Tell the player thread there is work to do. */ if(pthread_mutex_trylock(&player_thread_lock) == 0) { pthread_cond_signal(&buffer_ready); pthread_mutex_unlock(&player_thread_lock); } return(0); };
jack_read_midi(jack_nframes_t nframes) { jack_nframes_t i; midi_buf=jack_port_get_buffer(midi_port, nframes); jack_nframes_t num_events=jack_midi_get_event_count(midi_buf); for(i=0; i<num_events; i++) { if(jack_midi_event_get(&midi_event, midi_buf, i)) return; int status=midi_event.buffer[0]; jack_midi_data_t param=midi_event.buffer[1]; jack_midi_data_t value=midi_event.buffer[2]; //printf("JACK MIDI event: %x %x %x\n", status, param, value); int ev_type=status&0xf0; int channel=status&0x0f; switch(ev_type) { case SND_SEQ_EVENT_CONTROLLER: if(!midi_channels[channel].in_use) break; if(param==64) { if(value>64) midi_channels[channel].sustain=1; else midi_channels[channel].sustain=0; } else if(param==1) { // modulation controlling vibrato: value=0-127 midi_channels[channel].vibrato=value; //printf("%d\n", value); midi_channels[channel].vibrato_changed=1; } break; // case SND_SEQ_EVENT_KEYPRESS: case SND_SEQ_EVENT_CHANPRESS: if(!midi_channels[channel].in_use) break; midi_channels[channel].chanpress=value; midi_channels[channel].chanpress_changed=1; break; case SND_SEQ_EVENT_NOTEON: if(!midi_channels[channel].in_use) break; note_on(channel, param, value); break; case SND_SEQ_EVENT_NOTEOFF: if(!midi_channels[channel].in_use) break; note_off(channel, param); break; case SND_SEQ_EVENT_PITCHBEND: // value=-8192 to +8191 if(!midi_channels[channel].in_use) break; //int pitchbend=(value*128)|(param&0x7f); int pitchbend=(((value&0x7f)<<7)|(param&0x7f))-8192; //printf("got pitchbend %x %x: %x %d\n", param, value, pitchbend, pitchbend); midi_channels[channel].pitchbend=pitchbend; break; case SND_SEQ_EVENT_PGMCHANGE: if(midi_channels[channel].program==-1) break; //printf("prg change %d\n", value); midi_channels[channel].program=param; break; } } }
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); } }
static int process(jack_nframes_t nframes, void *arg) { int i; void* port_buf = jack_port_get_buffer(input_port, nframes); jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); jack_midi_event_t in_event; jack_nframes_t event_index = 0; jack_nframes_t event_count = jack_midi_get_event_count(port_buf); if(event_count > 1) { printf(" midisine: have %d events\n", event_count); for(i=0; i<event_count; i++) { jack_midi_event_get(&in_event, port_buf, i); printf(" event %d time is %d. 1st byte is 0x%x\n", i, in_event.time, *(in_event.buffer)); } /* printf("1st byte of 1st event addr is %p\n", in_events[0].buffer);*/ } jack_midi_event_get(&in_event, port_buf, 0); for(i = 0; i < nframes; i++) { if ((in_event.time == i) && (event_index < event_count)) { if (((*(in_event.buffer) & 0xf0)) == 0x90) { /* note on */ note = *(in_event.buffer + 1); if (*(in_event.buffer + 2) == 0) { note_on = 0.0; } else { note_on = (float)(*(in_event.buffer + 2)) / 127.f; } } else if (((*(in_event.buffer)) & 0xf0) == 0x80) { /* note off */ note = *(in_event.buffer + 1); note_on = 0.0; } event_index++; if(event_index < event_count) jack_midi_event_get(&in_event, port_buf, event_index); } ramp += note_frqs[note]; ramp = (ramp > 1.0) ? ramp - 2.0 : ramp; out[i] = note_on*sin(2*M_PI*ramp); } return 0; }
static int jackProcessCallback(jack_nframes_t nframes, void *arg) { JackAudioProvider *jap = static_cast<JackAudioProvider*>(arg); Synth *synth = jap->synth_; SampleBufferAllocator::reset(); typename Synth::InputBuffer input; typename Synth::OutputBuffer output; for (int i=0; i<Synth::InputBuffer::nChannels; i++) { jack_default_audio_sample_t *in = (jack_default_audio_sample_t*) jack_port_get_buffer(jap->inputPorts_[i], nframes); Sample *buf = input[i]; std::copy(in,in+nframes,buf); } void *midiBuf = jack_port_get_buffer(jap->midiInPort_, nframes); jack_nframes_t midiEventCount = jack_midi_get_event_count(midiBuf); jack_midi_event_t midiEvent; for (int i=0; i<midiEventCount; i++) { jack_midi_event_get(&midiEvent, midiBuf, i); unsigned char midiCommand = *(midiEvent.buffer) & 0xf0; //std::cout << "got midi command: " << int(midiCommand) << "\n"; if (midiEvent.size > 2) { unsigned char midiValue1 = *(midiEvent.buffer+1); unsigned char midiValue2 = *(midiEvent.buffer+2); int delay = midiEvent.time; switch (midiCommand) { case 0x80: synth->noteOff(midiValue1, midiValue2, delay); break; case 0x90: synth->noteOn(midiValue1, midiValue2, delay); break; case 0xb0: synth->controlChange(jap->midiCtrlMap_[midiValue1], midiValue2); break; case 0xe0: // pitch bend synth->controlChange(128, midiValue1 | (midiValue2<<7)); break; } } } synth->render(nframes, output, input); for (int i=0; i<Synth::OutputBuffer::nChannels; i++) { jack_default_audio_sample_t *out = (jack_default_audio_sample_t*) jack_port_get_buffer(jap->outputPorts_[i], nframes); Sample *buf = output[i]; std::copy(buf,buf+nframes,out); } return 0; }
int jackProcessIn( jack_nframes_t nframes, void *arg ) { JackMidiData *jData = ( (Arguments *) arg )->jackData; RtMidiIn :: RtMidiInData *rtData = ( (Arguments *) arg )->rtMidiIn; jack_midi_event_t event; jack_time_t long long time; // Is port created? if ( jData->port == NULL ) return 0; void *buff = jack_port_get_buffer( jData->port, nframes ); // We have midi events in buffer int evCount = jack_midi_get_event_count( buff ); if ( evCount > 0 ) { RtMidiIn::MidiMessage message; message.bytes.clear(); jack_midi_event_get( &event, buff, 0 ); for (unsigned int i = 0; i < event.size; i++ ) message.bytes.push_back( event.buffer[i] ); // Compute the delta time. time = jack_get_time(); if ( rtData->firstMessage == true ) rtData->firstMessage = false; else message.timeStamp = ( time - jData->lastTime ) * 0.000001; jData->lastTime = time; if ( rtData->usingCallback && !rtData->continueSysex ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback; callback( message.timeStamp, &message.bytes, rtData->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( rtData->queueLimit > rtData->queue.size() ) rtData->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } } return 0; }
int process(unsigned nframes, void *v) { (void) v; float seq_sqr[nframes]; float seq_noise[nframes]; float sqr[nframes]; float noise[nframes]; float lfo_f_out[nframes]; float filter_in[nframes]; float *output = (float*) jack_port_get_buffer(port, nframes); void *josc_buf = jack_port_get_buffer(josc, nframes); jack_midi_event_t in_event; jack_nframes_t event_count = jack_midi_get_event_count(josc_buf); // tag::buf-read[] if(event_count) { for(unsigned i=0; i<event_count; i++) { jack_midi_event_get(&in_event, josc_buf, i); assert(*in_event.buffer == '/'); RtDataImpl d; ports.dispatch((char*)in_event.buffer+1, d); } } while(uToB.hasNext()) { RtDataImpl d; d.matches = 0; ports.dispatch(uToB.read()+1, d); if(d.matches == 0) fprintf(stderr, "Unknown Port '%s'\n", uToB.peak()); } // end::buf-read gen_seq(seq_sqr, seq_noise, &seq, nframes); gen_noise(noise, seq_noise, nframes); gen_square(sqr, seq_sqr, &osc, nframes); gen_lfo(lfo_f_out, &lfo, nframes); do_sum(filter_in, noise, sqr, nframes); do_filter(output, filter_in, lfo_f_out, &filter, nframes); return 0; }
int jackprocess(jack_nframes_t nframes,void *arg) { int i,j,count; jack_midi_event_t midievent; jack_default_audio_sample_t *outl = (jack_default_audio_sample_t*) jack_port_get_buffer(outport_left, JackOUT->PERIOD); jack_default_audio_sample_t *outr = (jack_default_audio_sample_t*) jack_port_get_buffer(outport_right, JackOUT->PERIOD); float *data = (float *)jack_port_get_buffer(jack_midi_in, JackOUT->PERIOD); pthread_mutex_lock(&jmutex); count = jack_midi_get_event_count(data); for (int i = 0; i < count; i++) { jack_midi_event_get(&midievent, data, i); JackOUT->jack_process_midievents(&midievent); } JackOUT->Alg1s(JackOUT->PERIOD,0); for (i=0; i<JackOUT->PERIOD; i++) { j = i*2; outl[i]=JackOUT->buf[j]*JackOUT->Master_Volume; outr[i]=JackOUT->buf[j+1]*JackOUT->Master_Volume; } pthread_mutex_unlock(&jmutex); return(0); };
void midiMainLoop(void) { fprintf (stderr, "midiMainLoop\n"); jack_midi_event_t input_event; int timeout = 10*1000*1000+time_us(); // 10 seconds in microseconds //int exitMainLoop = 0; while (!exitMainLoop) { jack_nframes_t nframes = jack_cycle_wait(jack_client); /* Get input and output buffer pointers. */ void* input_buf = jack_port_get_buffer (jack_midi_input_port, nframes); //void* output_buf = jack_port_get_buffer (jack_midi_output_port, nframes); jack_nframes_t input_event_count = jack_midi_get_event_count(input_buf); if (input_event_count>0) { unsigned int event_index = 0; for (;event_index<input_event_count;event_index++) { if (0==jack_midi_event_get(&input_event, input_buf, event_index)) { if (input_event.size > 0) { printhex("receive:", input_event.buffer,input_event.size); int i = 0; for (; i < input_event.size; i++) { midiReceive(input_event.buffer[i]); } } } } } if (time_us() > timeout) { fprintf(stderr, "timeout\n"); exit(1); } } jack_end(); fprintf (stderr, "midiMainLoop:end\n"); }
int process(jack_nframes_t nframes, void *arg) { int j; data *par = (data *) arg; jack_midi_event_t *event = (jack_midi_event_t *) jack_port_get_buffer(par->inPort, nframes); int eCount = jack_midi_get_event_count(event); void *buffer = jack_port_get_buffer(par->outPort, nframes); jack_midi_clear_buffer(buffer); for (eCount, j = 0; eCount > 0; eCount--, j++) { jack_midi_event_t nextE; jack_midi_event_get(&nextE, event, j); // Filtering by channel char ch = nextE.buffer[0] & 0x0F; if (par->channelFilter >= 0) { if (ch != par->channelFilter) return 0; } if (nextE.buffer[0] & 0x80 || nextE.buffer[0] & 0x90) { if (nextE.buffer[1] >= par->currentNote) { nextE.buffer[0] &= 0xF0; nextE.buffer[0] += par->ch2Num; nextE.buffer[1] += par->ch2Shift; } else { nextE.buffer[0] &= 0xF0; nextE.buffer[0] += par->ch1Num; nextE.buffer[1] += par->ch1Shift; } } jack_midi_event_write(buffer, nextE.time, nextE.buffer, nextE.size); } return 0; }
static int process(jack_nframes_t nframes, void*) { void* mi = jack_port_get_buffer(input_port, nframes); float* lb = (float *) jack_port_get_buffer (output_portL, nframes); float* rb = (float *) jack_port_get_buffer (output_portR, nframes); jack_nframes_t event_count = jack_midi_get_event_count(mi); for (int i = 0; i < event_count; i++) { jack_midi_event_t event; jack_midi_event_get(&event, mi, i); int type = *(event.buffer) & 0xf0; if (type == 0x90) synth->play(Event(ME_NOTEON, 0, *(event.buffer+1), *(event.buffer+2))); else if (type == 0x80) synth->play(Event(ME_NOTEON, 0, *(event.buffer+1), 0)); else if (type == ME_CONTROLLER) synth->play(Event(ME_CONTROLLER, 0, *(event.buffer+1), *(event.buffer+2))); } synth->process(nframes, lb, rb, 1); return 0; }
void MidiJackDevice::collectMidiEvents()/*{{{*/ { if (!_readEnable) return; if (!_in_client_jackport) // p3.3.55 return; void* port_buf = jack_port_get_buffer(_in_client_jackport, segmentSize); // p3.3.55 jack_midi_event_t event; jack_nframes_t eventCount = jack_midi_get_event_count(port_buf); for (jack_nframes_t i = 0; i < eventCount; ++i) { jack_midi_event_get(&event, port_buf, i); #ifdef JACK_MIDI_DEBUG printf("MidiJackDevice::collectMidiEvents number:%d time:%d\n", i, event.time); #endif eventReceived(&event); } }/*}}}*/
static int copy_midi_data_to_buffer(jack_port_t *port, int buffer_size, struct cbox_midi_buffer *destination) { void *midi = jack_port_get_buffer(port, buffer_size); if (!midi) return 0; uint32_t event_count = jack_midi_get_event_count(midi); cbox_midi_buffer_clear(destination); for (uint32_t i = 0; i < event_count; i++) { jack_midi_event_t event; if (!jack_midi_event_get(&event, midi, i)) { if (!cbox_midi_buffer_write_event(destination, event.time, event.buffer, event.size)) return -i; } else return -i; } return event_count; }
// we read data from jack void MidiJack::JackMidiRead(jack_nframes_t nframes) { unsigned int i,b; void* port_buf = jack_port_get_buffer(m_input_port, nframes); jack_midi_event_t in_event; jack_nframes_t event_index = 0; jack_nframes_t event_count = jack_midi_get_event_count(port_buf); jack_midi_event_get(&in_event, port_buf, 0); for(i=0; i<nframes; i++) { if((in_event.time == i) && (event_index < event_count)) { // lmms is setup to parse bytes coming from a device // parse it byte by byte as it expects for(b=0;b<in_event.size;b++) parseData( *(in_event.buffer + b) ); event_index++; if(event_index < event_count) jack_midi_event_get(&in_event, port_buf, event_index); } } }
int process(jack_nframes_t nframes, void* arg) { TimerProcess.Start(); static uint64_t frametime = 0; TJackSynth* synth = static_cast<TJackSynth*>(arg); /* Process MIDI input */ void* inbuf = jack_port_get_buffer(MidiIn, nframes); jack_nframes_t event_count = jack_midi_get_event_count(inbuf); for (jack_nframes_t i = 0; i < event_count; i++) { jack_midi_event_t event; jack_midi_event_get(&event, inbuf, i); std::vector<uint8_t> data(event.buffer, event.buffer + event.size); synth->HandleMidi(data, frametime + event.time); } /* Send MIDI */ void* outbuf = jack_port_get_buffer(MidiOut, nframes); jack_midi_clear_buffer(outbuf); while (!MidiOutQueue.empty()) { const std::vector<uint8_t>& data = MidiOutQueue.front(); int ret = jack_midi_event_write(outbuf, 0, data.data(), data.size()); MidiOutQueue.pop(); if (ret != 0) { fprintf(stderr, "MIDI send error\n"); } } synth->Process(nframes); frametime += nframes; TimerProcess.Stop(); return 0; }
void jackProcess(const jack_nframes_t nframes) { #if DISTRHO_PLUGIN_NUM_INPUTS > 0 const float* audioIns[DISTRHO_PLUGIN_NUM_INPUTS]; for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) audioIns[i] = (const float*)jack_port_get_buffer(fPortAudioIns[i], nframes); #else static const float** audioIns = nullptr; #endif #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 float* audioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) audioOuts[i] = (float*)jack_port_get_buffer(fPortAudioOuts[i], nframes); #else static float** audioOuts = nullptr; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS jack_position_t pos; fTimePosition.playing = (jack_transport_query(fClient, &pos) == JackTransportRolling); if (pos.unique_1 == pos.unique_2) { fTimePosition.frame = pos.frame; if (pos.valid & JackTransportBBT) { fTimePosition.bbt.valid = true; fTimePosition.bbt.bar = pos.bar; fTimePosition.bbt.beat = pos.beat; fTimePosition.bbt.tick = pos.tick; fTimePosition.bbt.barStartTick = pos.bar_start_tick; fTimePosition.bbt.beatsPerBar = pos.beats_per_bar; fTimePosition.bbt.beatType = pos.beat_type; fTimePosition.bbt.ticksPerBeat = pos.ticks_per_beat; fTimePosition.bbt.beatsPerMinute = pos.beats_per_minute; } else fTimePosition.bbt.valid = false; } else { fTimePosition.bbt.valid = false; fTimePosition.frame = 0; } fPlugin.setTimePosition(fTimePosition); #endif #if DISTRHO_PLUGIN_IS_SYNTH void* const midiBuf = jack_port_get_buffer(fPortMidiIn, nframes); if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) { uint32_t midiEventCount = 0; MidiEvent midiEvents[eventCount]; jack_midi_event_t jevent; for (uint32_t i=0; i < eventCount; ++i) { if (jack_midi_event_get(&jevent, midiBuf, i) != 0) break; MidiEvent& midiEvent(midiEvents[midiEventCount++]); midiEvent.frame = jevent.time; midiEvent.size = jevent.size; if (midiEvent.size > MidiEvent::kDataSize) midiEvent.dataExt = jevent.buffer; else std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); } fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); } else { fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0); } #else fPlugin.run(audioIns, audioOuts, nframes); #endif }
void process_midi_input (jack_nframes_t nframes) { static int time_of_first_event = -1; int /*read,*/ events, i, channel; jack_midi_event_t event; int last_frame_time = jack_last_frame_time(jack_client); void * port_buffer = jack_port_get_buffer(input_port, nframes); if (port_buffer == NULL) { warn_from_jack_thread_context ( "jack_port_get_buffer failed, cannot receive anything." ); return; } #ifdef JACK_MIDI_NEEDS_NFRAMES events = jack_midi_get_event_count(port_buffer, nframes); #else events = jack_midi_get_event_count(port_buffer); #endif for (i = 0; i < events; ++i) { smf_event_t * smf_event; #ifdef JACK_MIDI_NEEDS_NFRAMES int read = jack_midi_event_get(&event, port_buffer, i, nframes); #else int read = jack_midi_event_get(&event, port_buffer, i); #endif if (read) { warn_from_jack_thread_context("jack_midi_event_get failed, RECEIVED NOTE LOST."); continue; } if (event.buffer[0] >= 0xF8) /* Ignore realtime messages. */ continue; if (time_of_first_event == -1) /* First event received? */ time_of_first_event = last_frame_time + event.time; smf_event = smf_event_new_from_pointer(event.buffer, event.size); if (smf_event == NULL) { warn_from_jack_thread_context ( "smf_event_from_pointer failed, RECEIVED NOTE LOST." ); continue; } // assert(smf_event->midi_buffer_length >= 1); channel = smf_event->midi_buffer[0] & 0x0F; smf_track_add_event_seconds ( tracks[channel], smf_event, nframes_to_seconds ( jack_last_frame_time(jack_client) + event.time - time_of_first_event ) ); } }
// rt static int _process(jack_nframes_t nsamples, void *data) { prog_t *handle = data; bin_t *bin = &handle->bin; sp_app_t *app = bin->app; #if defined(JACK_HAS_CYCLE_TIMES) clock_gettime(CLOCK_REALTIME, &handle->ntp); handle->ntp.tv_sec += JAN_1970; // convert NTP to OSC time jack_nframes_t offset = jack_frames_since_cycle_start(handle->client); float T; jack_get_cycle_times(handle->client, &handle->cycle.cur_frames, &handle->cycle.cur_usecs, &handle->cycle.nxt_usecs, &T); (void)T; handle->cycle.ref_frames = handle->cycle.cur_frames + offset; // calculate apparent period double diff = 1e-6 * (handle->cycle.nxt_usecs - handle->cycle.cur_usecs); // calculate apparent samples per period handle->cycle.dT = nsamples / diff; handle->cycle.dTm1 = 1.0 / handle->cycle.dT; #endif // get transport position jack_position_t pos; jack_transport_state_t rolling = jack_transport_query(handle->client, &pos) == JackTransportRolling; int trans_changed = (rolling != handle->trans.rolling) || (pos.frame != handle->trans.frame) || (pos.beats_per_bar != handle->trans.beats_per_bar) || (pos.beat_type != handle->trans.beat_type) || (pos.ticks_per_beat != handle->trans.ticks_per_beat) || (pos.beats_per_minute != handle->trans.beats_per_minute); const size_t sample_buf_size = sizeof(float) * nsamples; const sp_app_system_source_t *sources = sp_app_get_system_sources(app); const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app); if(sp_app_bypassed(app)) // aka loading state { //fprintf(stderr, "app is bypassed\n"); // clear output buffers for(const sp_app_system_sink_t *sink=sinks; sink->type != SYSTEM_PORT_NONE; sink++) { switch(sink->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: case SYSTEM_PORT_COM: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); memset(out_buf, 0x0, sample_buf_size); break; } case SYSTEM_PORT_MIDI: case SYSTEM_PORT_OSC: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); jack_midi_clear_buffer(out_buf); break; } } } bin_process_pre(bin, nsamples, true); bin_process_post(bin); return 0; } //TODO use __builtin_assume_aligned // fill input buffers for(const sp_app_system_source_t *source=sources; source->type != SYSTEM_PORT_NONE; source++) { switch(source->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { const void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); memcpy(source->buf, in_buf, sample_buf_size); break; } case SYSTEM_PORT_MIDI: { void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); if(ref && trans_changed) ref = _trans_event(handle, forge, rolling, &pos); int n = jack_midi_get_event_count(in_buf); for(int i=0; i<n; i++) { jack_midi_event_t mev; jack_midi_event_get(&mev, in_buf, i); //add jack midi event to in_buf if(ref) ref = lv2_atom_forge_frame_time(forge, mev.time); if(ref) ref = lv2_atom_forge_atom(forge, mev.size, handle->midi_MidiEvent); if(ref) ref = lv2_atom_forge_raw(forge, mev.buffer, mev.size); if(ref) lv2_atom_forge_pad(forge, mev.size); } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } case SYSTEM_PORT_OSC: { void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); if(ref && trans_changed) ref = _trans_event(handle, forge, rolling, &pos); int n = jack_midi_get_event_count(in_buf); for(int i=0; i<n; i++) { jack_midi_event_t mev; jack_midi_event_get(&mev, (void *)in_buf, i); //add jack osc event to in_buf if(osc_check_packet(mev.buffer, mev.size)) { if(ref) ref = lv2_atom_forge_frame_time(forge, mev.time); handle->ref = ref; osc_dispatch_method(mev.buffer, mev.size, methods, _bundle_in, _bundle_out, handle); ref = handle->ref; } } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } case SYSTEM_PORT_COM: { void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); const LV2_Atom_Object *obj; size_t size; while((obj = varchunk_read_request(bin->app_from_com, &size))) { if(ref) ref = lv2_atom_forge_frame_time(forge, 0); if(ref) ref = lv2_atom_forge_raw(forge, obj, size); if(ref) lv2_atom_forge_pad(forge, size); varchunk_read_advance(bin->app_from_com); } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } } } // update transport state handle->trans.rolling = rolling; handle->trans.frame = rolling ? handle->trans.frame + nsamples : pos.frame; handle->trans.beats_per_bar = pos.beats_per_bar; handle->trans.beat_type = pos.beat_type; handle->trans.ticks_per_beat = pos.ticks_per_beat; handle->trans.beats_per_minute = pos.beats_per_minute; bin_process_pre(bin, nsamples, false); // fill output buffers for(const sp_app_system_sink_t *sink=sinks; sink->type != SYSTEM_PORT_NONE; sink++) { switch(sink->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); memcpy(out_buf, sink->buf, sample_buf_size); break; } case SYSTEM_PORT_MIDI: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); const LV2_Atom_Sequence *seq_out = sink->buf; // fill midi output buffer jack_midi_clear_buffer(out_buf); if(seq_out) { LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom *atom = &ev->body; if(atom->type != handle->midi_MidiEvent) continue; // ignore non-MIDI events jack_midi_event_write(out_buf, ev->time.frames, LV2_ATOM_BODY_CONST(atom), atom->size); } } break; } case SYSTEM_PORT_OSC: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); const LV2_Atom_Sequence *seq_out = sink->buf; // fill midi output buffer jack_midi_clear_buffer(out_buf); if(seq_out) { LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body; handle->osc_ptr = handle->osc_buf; handle->osc_end = handle->osc_buf + OSC_SIZE; osc_atom_event_unroll(&handle->oforge, obj, _bundle_push_cb, _bundle_pop_cb, _message_cb, handle); size_t size = handle->osc_ptr ? handle->osc_ptr - handle->osc_buf : 0; if(size) { jack_midi_event_write(out_buf, ev->time.frames, handle->osc_buf, size); } } } break; } case SYSTEM_PORT_COM: { const LV2_Atom_Sequence *seq_out = sink->buf; LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom *atom = (const LV2_Atom *)&ev->body; // try do process events directly bin->advance_ui = sp_app_from_ui(bin->app, atom); if(!bin->advance_ui) // queue event in ringbuffer instead { //fprintf(stderr, "plugin ui direct is blocked\n"); void *ptr; size_t size = lv2_atom_total_size(atom); if((ptr = varchunk_write_request(bin->app_from_app, size))) { memcpy(ptr, atom, size); varchunk_write_advance(bin->app_from_app, size); } else { //fprintf(stderr, "app_from_ui ringbuffer full\n"); //FIXME } } } break; } } } bin_process_post(bin); return 0; }
// JACK specifics. int qmidinetJackMidiDevice::process ( jack_nframes_t nframes ) { jack_nframes_t buffer_size = jack_get_buffer_size(m_pJackClient); m_last_frame_time = jack_last_frame_time(m_pJackClient); // Enqueue/dequeue events // to/from ring-buffers... for (int i = 0; i < m_nports; ++i) { if (m_ppJackPortIn && m_ppJackPortIn[i] && m_pJackBufferIn) { void *pvBufferIn = jack_port_get_buffer(m_ppJackPortIn[i], nframes); const int nevents = jack_midi_get_event_count(pvBufferIn); const unsigned int nlimit = jack_ringbuffer_write_space(m_pJackBufferIn); unsigned char achBuffer[nlimit]; unsigned char *pchBuffer = &achBuffer[0]; unsigned int nwrite = 0; for (int n = 0; n < nevents; ++n) { if (nwrite + sizeof(qmidinetJackMidiEvent) >= nlimit) break; qmidinetJackMidiEvent *pJackEventIn = (struct qmidinetJackMidiEvent *) pchBuffer; jack_midi_event_get(&pJackEventIn->event, pvBufferIn, n); if (nwrite + sizeof(qmidinetJackMidiEvent) + pJackEventIn->event.size >= nlimit) break; pJackEventIn->port = i; pchBuffer += sizeof(qmidinetJackMidiEvent); nwrite += sizeof(qmidinetJackMidiEvent); ::memcpy(pchBuffer, pJackEventIn->event.buffer, pJackEventIn->event.size); pchBuffer += pJackEventIn->event.size; nwrite += pJackEventIn->event.size; } if (nwrite > 0) { jack_ringbuffer_write(m_pJackBufferIn, (const char *) achBuffer, nwrite); } } if (m_ppJackPortOut && m_ppJackPortOut[i] && m_pJackBufferOut) { void *pvBufferOut = jack_port_get_buffer(m_ppJackPortOut[i], nframes); jack_midi_clear_buffer(pvBufferOut); const unsigned int nlimit = jack_midi_max_event_size(pvBufferOut); unsigned int nread = 0; qmidinetJackMidiEvent ev; while (jack_ringbuffer_peek(m_pJackBufferOut, (char *) &ev, sizeof(ev)) == sizeof(ev) && nread < nlimit) { if (ev.port != i) break; if (ev.event.time > m_last_frame_time) break; jack_nframes_t offset = m_last_frame_time - ev.event.time; if (offset > buffer_size) offset = 0; else offset = buffer_size - offset; jack_ringbuffer_read_advance(m_pJackBufferOut, sizeof(ev)); jack_midi_data_t *pMidiData = jack_midi_event_reserve(pvBufferOut, offset, ev.event.size); if (pMidiData) jack_ringbuffer_read(m_pJackBufferOut, (char *) pMidiData, ev.event.size); else jack_ringbuffer_read_advance(m_pJackBufferOut, ev.event.size); nread += ev.event.size; } } } if (m_pJackBufferIn && jack_ringbuffer_read_space(m_pJackBufferIn) > 0) m_pRecvThread->sync(); return 0; }
int process(jack_nframes_t nframes, void *arg) { struct guitarseq *guitarseq = arg; if(!guitarseq) { fprintf(stderr, "No guitarseq instance!\n"); return 1; } void* port_buf; jack_nframes_t now = jack_frame_time (guitarseq->jack_client); //Output port_buf = jack_port_get_buffer(guitarseq->out_port, nframes); jack_midi_clear_buffer(port_buf); while (1) { jack_nframes_t time; //TODO: Do a safer read, in case only part of the message is here if (!jack_ringbuffer_read (guitarseq->out_buffer, (char *)&time, sizeof(time))) { break; } // from the future? if (time >= now) { break; } // time it right jack_nframes_t offset = time - now + nframes - 1; // get the size of the event size_t size; jack_ringbuffer_read(guitarseq->out_buffer, (char *)&size, sizeof(size)); INFO("out event at %u%+d size %zu\n", now, offset, size); if (offset > nframes) // from the past, somehow. cram it in at the front offset = 0; // proceed to giving it to jack jack_midi_data_t *buffer = jack_midi_event_reserve (port_buf, offset, size); if(buffer) { jack_ringbuffer_read(guitarseq->out_buffer, (char *)buffer, size); } else { // throw it away :( TODO: find more jack_ringbuffer_read_advance (guitarseq->out_buffer, size); ERROR("threw away MIDI event - no space reserved at time %u offset %d\n",time,offset); } } // Input port_buf = jack_port_get_buffer(guitarseq->in_port, nframes); jack_nframes_t event_count = jack_midi_get_event_count(port_buf); for(jack_nframes_t i=0; i<event_count; i++) { jack_midi_event_t in_event; jack_midi_event_get(&in_event, port_buf, i); //adds a note to the ringbuffer if (jack_ringbuffer_write_space(guitarseq->in_buffer) >= sizeof(in_event.time)+sizeof(in_event.size)+in_event.size) { jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.time, sizeof(in_event.time)); jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.size, sizeof(in_event.size)); jack_ringbuffer_write(guitarseq->in_buffer, (char *)in_event.buffer, in_event.size); } else { ERROR("Couldn't write to ringbuffer at %u, %zu midi data bytes lost\n", in_event.time, in_event.size); } } return 0; }
void ModeHandler::process(const jack_nframes_t nframes) { void* inPortBuf = jack_port_get_buffer(m_inputPort, nframes); void* outPortBuf = jack_port_get_buffer(m_outputPort, nframes); jack_midi_clear_buffer(outPortBuf); const jack_transport_state_t state = jack_transport_query(m_client, nullptr); const jack_nframes_t eventCount = jack_midi_get_event_count(inPortBuf); for (size_t i = 0; i < eventCount; ++i) { jack_midi_event_t inEvent; jack_midi_event_get(&inEvent, inPortBuf, i); const jack_midi_data_t cmd = inEvent.buffer[0] & 0xf0; switch (cmd) { case MIDI_NOTEON: case MIDI_NOTEOFF: { const jack_midi_data_t note = inEvent.buffer[1]; const jack_midi_data_t velocity = inEvent.buffer[2]; int noteToUse = note; // we only map on a note on // on a note off we use the previously mapped note // and only is transport is rolling if (cmd == MIDI_NOTEON && velocity > 0) { if (state == JackTransportRolling) { const int newNote = transpose(m_offset, m_quirkOffset, note); m_mappedNotes[note] = newNote; noteToUse = newNote; } } else { // NOTEOFF if (m_mappedNotes[note] != NOT_MAPPED) { noteToUse = m_mappedNotes[note]; m_mappedNotes[note] = NOT_MAPPED; } } if (noteToUse != SKIP) { jack_midi_data_t data[3]; data[0] = inEvent.buffer[0]; data[1] = noteToUse;; data[2] = inEvent.buffer[2]; jack_midi_event_write(outPortBuf, inEvent.time, data, 3); } break; } default: { // just forward everything else jack_midi_event_write(outPortBuf, inEvent.time, inEvent.buffer, inEvent.size); } } } }
int jack_audio_callback (jack_nframes_t nframes, void *arg) { jack_default_audio_sample_t **out = j_output_bufferptrs; int i; void *jack_midi_buf = NULL; int midi_events = 0; jack_nframes_t midi_tme_proc = 0; if (!synth_ready) { for (i=0;i<AUDIO_CHANNELS;i++) { out[i] = (jack_default_audio_sample_t*) jack_port_get_buffer (j_output_port[i], nframes); memset(out[i], 0, nframes*sizeof(jack_default_audio_sample_t)); } return (0); } if (use_jack_midi) { jack_midi_buf = jack_port_get_buffer(jack_midi_port, nframes); midi_events = jack_midi_get_event_count(jack_midi_buf); } for (i=0;i<AUDIO_CHANNELS;i++) { out[i] = (jack_default_audio_sample_t*) jack_port_get_buffer (j_output_port[i], nframes); } static int boffset = BUFFER_SIZE_SAMPLES; jack_nframes_t written = 0; while (written < nframes) { int nremain = nframes - written; if (boffset >= BUFFER_SIZE_SAMPLES) { if (use_jack_midi) { for (i=0; i<midi_events; i++) { jack_midi_event_t ev; jack_midi_event_get(&ev, jack_midi_buf, i); if (ev.time >= written && ev.time < (written + BUFFER_SIZE_SAMPLES)) parse_raw_midi_data(arg, ev.buffer, ev.size); } midi_tme_proc = written + BUFFER_SIZE_SAMPLES; } boffset = 0; oscGenerateFragment (inst.synth, bufA, BUFFER_SIZE_SAMPLES); preamp (inst.preamp, bufA, bufB, BUFFER_SIZE_SAMPLES); reverb (inst.reverb, bufB, bufC, BUFFER_SIZE_SAMPLES); #ifdef HAVE_ZITACONVOLVE whirlProc2(inst.whirl, bufC, NULL, NULL, bufH[0], bufH[1], bufD[0], bufD[1], BUFFER_SIZE_SAMPLES); const float *horn[2] = { bufH[0], bufH[1] }; const float *drum[2] = { bufD[0], bufD[1] }; float *out[2] = { bufJ[0], bufJ[1] }; convolve(horn, out, 2, BUFFER_SIZE_SAMPLES); mixdown(out, drum, AUDIO_CHANNELS, BUFFER_SIZE_SAMPLES); #else whirlProc(inst.whirl, bufC, bufJ[0], bufJ[1], BUFFER_SIZE_SAMPLES); #endif } int nread = MIN(nremain, (BUFFER_SIZE_SAMPLES - boffset)); for (i=0;i< AUDIO_CHANNELS; i++) { memcpy(&out[i][written], &bufJ[i][boffset], nread*sizeof(float)); } written+=nread; boffset+=nread; } if (use_jack_midi) { /* process remaining MIDI events * IF nframes < BUFFER_SIZE_SAMPLES OR nframes != N * BUFFER_SIZE_SAMPLES */ for (i=0; i<midi_events; i++) { jack_midi_event_t ev; jack_midi_event_get(&ev, jack_midi_buf, i); if (ev.time >= midi_tme_proc) parse_raw_midi_data(arg, ev.buffer, ev.size); } } return(0); }
int MidiBuffer::numberOfEvents() { return jack_midi_get_event_count(_jackBuffer); }
static int handle_process(jack_nframes_t frames, void *arg) { jack_midi_data_t *buffer; jack_midi_event_t event; jack_nframes_t event_count; jack_nframes_t event_time; jack_nframes_t frame; size_t i; jack_nframes_t last_frame_time; jack_midi_data_t *message; jack_time_t microseconds; void *port_buffer; jack_time_t time; jack_midi_clear_buffer(jack_port_get_buffer(out_port, frames)); switch (process_state) { case 0: /* State: initializing */ switch (wait_semaphore(init_semaphore, 0)) { case -1: set_process_error(SOURCE_WAIT_SEMAPHORE, get_semaphore_error()); /* Fallthrough on purpose */ case 0: return 0; } highest_latency = 0; lowest_latency = 0; messages_received = 0; messages_sent = 0; process_state = 1; total_latency = 0; total_latency_time = 0; unexpected_messages = 0; xrun_count = 0; jack_port_get_latency_range(remote_in_port, JackCaptureLatency, &in_latency_range); jack_port_get_latency_range(remote_out_port, JackPlaybackLatency, &out_latency_range); goto send_message; case 1: /* State: processing */ port_buffer = jack_port_get_buffer(in_port, frames); event_count = jack_midi_get_event_count(port_buffer); last_frame_time = jack_last_frame_time(client); for (i = 0; i < event_count; i++) { jack_midi_event_get(&event, port_buffer, i); message = (messages_received % 2) ? message_2 : message_1; if ((event.size == message_size) && (! memcmp(message, event.buffer, message_size * sizeof(jack_midi_data_t)))) { goto found_message; } unexpected_messages++; } microseconds = jack_frames_to_time(client, last_frame_time) - last_activity_time; if ((microseconds / 1000000) >= timeout) { set_process_error(SOURCE_PROCESS, ERROR_MSG_TIMEOUT); } break; found_message: event_time = last_frame_time + event.time; frame = event_time - last_activity; time = jack_frames_to_time(client, event_time) - last_activity_time; if ((! highest_latency) || (frame > highest_latency)) { highest_latency = frame; highest_latency_time = time; } if ((! lowest_latency) || (frame < lowest_latency)) { lowest_latency = frame; lowest_latency_time = time; } latency_time_values[messages_received] = time; latency_values[messages_received] = frame; total_latency += frame; total_latency_time += time; messages_received++; if (messages_received == samples) { process_state = 2; if (! signal_semaphore(process_semaphore)) { /* Sigh ... */ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error()); } break; } send_message: frame = (jack_nframes_t) ((((double) rand()) / RAND_MAX) * frames); if (frame >= frames) { frame = frames - 1; } port_buffer = jack_port_get_buffer(out_port, frames); buffer = jack_midi_event_reserve(port_buffer, frame, message_size); if (buffer == NULL) { set_process_error(SOURCE_EVENT_RESERVE, ERROR_RESERVE); break; } message = (messages_sent % 2) ? message_2 : message_1; memcpy(buffer, message, message_size * sizeof(jack_midi_data_t)); last_activity = jack_last_frame_time(client) + frame; last_activity_time = jack_frames_to_time(client, last_activity); messages_sent++; case 2: /* State: finished - do nothing */ case -1: /* State: error - do nothing */ case -2: /* State: signalled - do nothing */ ; } return 0; }