static void port_event (LV2UI_Handle handle, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer) { BITui* ui = (BITui*)handle; const EBULV2URIs* uris = &ui->uris; if (format != uris->atom_eventTransfer) { return; } LV2_Atom* atom = (LV2_Atom*)buffer; if (atom->type != uris->atom_Blank && atom->type != uris->atom_Object) { fprintf (stderr, "UI: Unknown message type.\n"); return; } LV2_Atom_Object* obj = (LV2_Atom_Object*)atom; if (obj->body.otype == uris->mtr_control) { int k; float v; get_cc_key_value (&ui->uris, obj, &k, &v); if (k == CTL_SAMPLERATE) { if (v > 0) { ui->rate = v; } queue_draw (ui->m0); } } else if (obj->body.otype == uris->bim_stats) { LV2_Atom *bcnt = NULL; LV2_Atom *bmin = NULL; LV2_Atom *bmax = NULL; LV2_Atom *bnan = NULL; LV2_Atom *binf = NULL; LV2_Atom *bden = NULL; LV2_Atom *bpos = NULL; LV2_Atom *bnul = NULL; LV2_Atom *bdat = NULL; if (9 == lv2_atom_object_get (obj, uris->ebu_integr_time, &bcnt, uris->bim_zero, &bnul, uris->bim_pos, &bpos, uris->bim_max, &bmax, uris->bim_min, &bmin, uris->bim_nan, &bnan, uris->bim_inf, &binf, uris->bim_den, &bden, uris->bim_data, &bdat, NULL) && bcnt && bnul && bpos && bmin && bmax && bnan && binf && bden && bdat && bcnt->type == uris->atom_Long && bpos->type == uris->atom_Int && bnul->type == uris->atom_Int && bmin->type == uris->atom_Double && bmax->type == uris->atom_Double && bnan->type == uris->atom_Int && binf->type == uris->atom_Int && bden->type == uris->atom_Int && bdat->type == uris->atom_Vector ) { CB_INT(bnan, update_oops, 0); CB_INT(binf, update_oops, 1); CB_INT(bden, update_oops, 2); PARSE_A_INT(bpos, ui->f_pos); PARSE_A_INT(bnul, ui->f_zero); CB_DBL(bmin, update_minmax, 0); CB_DBL(bmax, update_minmax, 1); LV2_Atom_Vector* data = (LV2_Atom_Vector*)LV2_ATOM_BODY(bdat); if (data->atom.type == uris->atom_Int) { const size_t n_elem = (bdat->size - sizeof (LV2_Atom_Vector_Body)) / data->atom.size; assert (n_elem == BIM_LAST); const int32_t *d = (int32_t*) LV2_ATOM_BODY(&data->atom); memcpy (ui->flt, d, sizeof (int32_t) * n_elem); } update_time (ui, (uint64_t)(((LV2_Atom_Long*)bcnt)->body)); btn_start_sens (ui); // maybe set 2^31 limit. queue_draw (ui->m0); } } else if (obj->body.otype == uris->bim_information) { LV2_Atom *ii = NULL; LV2_Atom *av = NULL; lv2_atom_object_get (obj, uris->ebu_integrating, &ii, uris->bim_averaging, &av, NULL); ui->disable_signals = true; if (ii && ii->type == uris->atom_Bool) { bool ix = ((LV2_Atom_Bool*)ii)->body; robtk_cbtn_set_active (ui->btn_freeze, !ix); } if (av && av->type == uris->atom_Bool) { bool ix = ((LV2_Atom_Bool*)av)->body; robtk_cbtn_set_active (ui->btn_avg, ix); } ui->disable_signals = false; } else { fprintf (stderr, "UI: Unknown control message.\n"); } }
static void run(LV2_Handle instance, uint32_t n_samples) { B3S* b3s = (B3S*)instance; float* audio[2]; audio[0] = b3s->outL; audio[1] = b3s->outR; /* prepare outgoing MIDI */ const uint32_t capacity = b3s->midiout->atom.size; static bool warning_printed = false; if (!warning_printed && capacity < 4096) { warning_printed = true; fprintf(stderr, "B3LV2: LV message buffer is only %d bytes. Expect problems.\n", capacity); fprintf(stderr, "B3LV2: if your LV2 host allows one to configure a buffersize use at least 4kBytes.\n"); } lv2_atom_forge_set_buffer(&b3s->forge, (uint8_t*)b3s->midiout, capacity); lv2_atom_forge_sequence_head(&b3s->forge, &b3s->frame, 0); uint32_t written = 0; if (b3s->queue_panic) { b3s->queue_panic = 0; midi_panic(b3s->inst); } /* Process incoming events from GUI and handle MIDI events */ if (b3s->midiin) { LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(b3s->midiin)->body); while(!lv2_atom_sequence_is_end(&(b3s->midiin)->body, (b3s->midiin)->atom.size, ev)) { if (ev->body.type == b3s->uris.midi_MidiEvent) { /* process midi messages from player */ if (written + BUFFER_SIZE_SAMPLES < ev->time.frames && ev->time.frames < n_samples) { /* first syntheize sound up until the message timestamp */ written = synthSound(b3s, written, ev->time.frames, audio); } /* send midi message to synth, CC's will trigger hook -> update GUI */ parse_raw_midi_data(b3s->inst, (uint8_t*)(ev+1), ev->body.size); } else if (ev->body.type == b3s->uris.atom_Blank || ev->body.type == b3s->uris.atom_Object) { /* process messages from GUI */ const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; if (obj->body.otype == b3s->uris.sb3_uiinit) { b3s->update_gui_now = 1; } else if (obj->body.otype == b3s->uris.sb3_uimccquery) { midi_loopCCAssignment(b3s->inst->midicfg, 7, mcc_cb, b3s); } else if (obj->body.otype == b3s->uris.sb3_uimccset) { const LV2_Atom* cmd = NULL; const LV2_Atom* flags = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &flags, b3s->uris.sb3_ccval, &cmd, 0); if (cmd && flags) { midi_uiassign_cc(b3s->inst->midicfg, (const char*)LV2_ATOM_BODY(cmd), ((LV2_Atom_Int*)flags)->body); } } else if (obj->body.otype == b3s->uris.sb3_midipgm) { const LV2_Atom* key = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &key, 0); if (key) { installProgram(b3s->inst, ((LV2_Atom_Int*)key)->body); } } else if (obj->body.otype == b3s->uris.sb3_midisavepgm) { const LV2_Atom* pgm = NULL; const LV2_Atom* name = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &pgm, b3s->uris.sb3_ccval, &name, 0); if (pgm && name) { saveProgramm(b3s->inst, (int) ((LV2_Atom_Int*)pgm)->body, (char*) LV2_ATOM_BODY(name), 0); b3s->update_pgm_now = 1; } } else if (obj->body.otype == b3s->uris.sb3_loadpgm) { iowork(b3s, obj, CMD_LOADPGM); } else if (obj->body.otype == b3s->uris.sb3_loadcfg) { iowork(b3s, obj, CMD_LOADCFG); } else if (obj->body.otype == b3s->uris.sb3_savepgm) { iowork(b3s, obj, CMD_SAVEPGM); } else if (obj->body.otype == b3s->uris.sb3_savecfg) { iowork(b3s, obj, CMD_SAVECFG); } else if (obj->body.otype == b3s->uris.sb3_cfgstr) { if (!b3s->inst_offline) { advanced_config_set(b3s, obj); } } else if (obj->body.otype == b3s->uris.sb3_control) { b3s->suspend_ui_msg = 1; const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; char *k; int v; if (!get_cc_key_value(&b3s->uris, obj, &k, &v)) { #ifdef DEBUGPRINT fprintf(stderr, "B3LV2: callMIDIControlFunction(..,\"%s\", %d);\n", k, v); #endif callMIDIControlFunction(b3s->inst->midicfg, k, v); } b3s->suspend_ui_msg = 0; } } ev = lv2_atom_sequence_next(ev); } } /* synthesize [remaining] sound */ synthSound(b3s, written, n_samples, audio); /* send active keys to GUI - IFF changed */ bool keychanged = false; for (int i = 0 ; i < MAX_KEYS/32; ++i) { if (b3s->active_keys[i] != b3s->inst->synth->_activeKeys[i]) { keychanged = true; } b3s->active_keys[i] = b3s->inst->synth->_activeKeys[i]; } if (keychanged) { LV2_Atom_Forge_Frame frame; lv2_atom_forge_frame_time(&b3s->forge, 0); x_forge_object(&b3s->forge, &frame, 1, b3s->uris.sb3_activekeys); lv2_atom_forge_property_head(&b3s->forge, b3s->uris.sb3_keyarrary, 0); lv2_atom_forge_vector(&b3s->forge, sizeof(unsigned int), b3s->uris.atom_Int, MAX_KEYS/32, b3s->active_keys); lv2_atom_forge_pop(&b3s->forge, &frame); } /* check for new instances */ postrun(b3s); if (b3s->update_gui_now) { b3s->update_gui_now = 0; b3s->update_pgm_now = 1; b3s->suspend_ui_msg = 1; rc_loop_state(b3s->inst->state, rc_cb, b3s); b3s->suspend_ui_msg = 0; forge_kvconfigmessage(&b3s->forge, &b3s->uris, b3s->uris.sb3_cfgkv, "lv2.info", b3s->lv2nfo); forge_kvcontrolmessage(&b3s->forge, &b3s->uris, "special.init", (int32_t) b3s->thirtysec); } else if (b3s->update_pgm_now) { b3s->update_pgm_now = 0; loopProgammes(b3s->inst->progs, 1, pgm_cb, b3s); } }
static void bim_run(LV2_Handle instance, uint32_t n_samples) { LV2meter* self = (LV2meter*)instance; const uint32_t capacity = self->notify->atom.size; assert(capacity > 920); lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->notify, capacity); lv2_atom_forge_sequence_head(&self->forge, &self->frame, 0); if (self->send_state_to_ui && self->ui_active) { self->send_state_to_ui = false; forge_kvcontrolmessage(&self->forge, &self->uris, self->uris.mtr_control, CTL_SAMPLERATE, self->rate); } /* Process incoming events from GUI */ if (self->control) { LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(self->control)->body); while(!lv2_atom_sequence_is_end(&(self->control)->body, (self->control)->atom.size, ev)) { if (ev->body.type == self->uris.atom_Blank || ev->body.type == self->uris.atom_Object) { const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; if (obj->body.otype == self->uris.mtr_meters_on) { self->ui_active = true; self->send_state_to_ui = true; } else if (obj->body.otype == self->uris.mtr_meters_off) { self->ui_active = false; } else if (obj->body.otype == self->uris.mtr_meters_cfg) { int k; float v; get_cc_key_value(&self->uris, obj, &k, &v); switch (k) { case CTL_START: self->ebu_integrating = true; break; case CTL_PAUSE: self->ebu_integrating = false; break; case CTL_RESET: bim_reset(self); self->send_state_to_ui = true; break; case CTL_AVERAGE: self->bim_average = true; break; case CTL_WINDOWED: self->bim_average = false; break; default: break; } } } ev = lv2_atom_sequence_next(ev); } } #if 0 static uint32_t max_post = 0; if (self->notify->atom.size > max_post) { max_post = self->notify->atom.size; printf("new post parse: %d\n", max_post); } #endif /* process */ if (self->ebu_integrating && self->integration_time < 2147483647) { /* currently 'self->histS' is int32, * the max peak that can be recorded is 2^31, * for now we simply limit data-acquisition to at * most 2^31 points. */ if (self->integration_time > 2147483647 - n_samples) { self->integration_time = 2147483647; } else { for (uint32_t s = 0; s < n_samples; ++s) { float_stats(self, self->input[0] + s); } self->integration_time += n_samples; } } const int fps_limit = n_samples * ceil(self->rate / (5.f * n_samples)); // ~ 5fps self->radar_resync += n_samples; if (self->radar_resync >= fps_limit || self->send_state_to_ui) { self->radar_resync = self->radar_resync % fps_limit; if (self->ui_active && (self->ebu_integrating || self->send_state_to_ui)) { LV2_Atom_Forge_Frame frame; lv2_atom_forge_frame_time(&self->forge, 0); x_forge_object(&self->forge, &frame, 1, self->uris.bim_stats); lv2_atom_forge_property_head(&self->forge, self->uris.ebu_integr_time, 0); lv2_atom_forge_long(&self->forge, self->integration_time); lv2_atom_forge_property_head(&self->forge, self->uris.bim_zero, 0); lv2_atom_forge_int(&self->forge, self->bim_zero); lv2_atom_forge_property_head(&self->forge, self->uris.bim_pos, 0); lv2_atom_forge_int(&self->forge, self->bim_pos); lv2_atom_forge_property_head(&self->forge, self->uris.bim_max, 0); lv2_atom_forge_double(&self->forge, self->bim_max); lv2_atom_forge_property_head(&self->forge, self->uris.bim_min, 0); lv2_atom_forge_double(&self->forge, self->bim_min); lv2_atom_forge_property_head(&self->forge, self->uris.bim_nan, 0); lv2_atom_forge_int(&self->forge, self->bim_nan); lv2_atom_forge_property_head(&self->forge, self->uris.bim_inf, 0); lv2_atom_forge_int(&self->forge, self->bim_inf); lv2_atom_forge_property_head(&self->forge, self->uris.bim_den, 0); lv2_atom_forge_int(&self->forge, self->bim_den); lv2_atom_forge_property_head(&self->forge, self->uris.bim_data, 0); lv2_atom_forge_vector(&self->forge, sizeof(int32_t), self->uris.atom_Int, BIM_LAST, self->histS); lv2_atom_forge_pop(&self->forge, &frame); } if (self->ui_active) { LV2_Atom_Forge_Frame frame; lv2_atom_forge_frame_time(&self->forge, 0); x_forge_object(&self->forge, &frame, 1, self->uris.bim_information); lv2_atom_forge_property_head(&self->forge, self->uris.ebu_integrating, 0); lv2_atom_forge_bool(&self->forge, self->ebu_integrating); lv2_atom_forge_property_head(&self->forge, self->uris.bim_averaging, 0); lv2_atom_forge_bool(&self->forge, self->bim_average); lv2_atom_forge_pop(&self->forge, &frame); } if (!self->bim_average) { bim_clear (self); } } /* foward audio-data */ if (self->input[0] != self->output[0]) { memcpy(self->output[0], self->input[0], sizeof(float) * n_samples); } #if 0 //printf("forged %d bytes\n", self->notify->atom.size); static uint32_t max_cap = 0; if (self->notify->atom.size > max_cap) { max_cap = self->notify->atom.size; printf("new max: %d (of %d avail)\n", max_cap, capacity); } #endif }