Exemplo n.º 1
0
static LV2_State_Status
state_restore(
    LV2_Handle                  instance,
    LV2_State_Retrieve_Function retrieve,
    LV2_State_Handle            handle,
    uint32_t                    flags,
    const LV2_Feature* const*   features)
{
  SiSco* self = (SiSco*)instance;
  size_t   size;
  uint32_t type;
  uint32_t valflags;

  const void * value = retrieve(handle, self->uris.ui_state_grid, &size, &type, &valflags);
  if (value && size == sizeof(uint32_t) && type == self->uris.atom_Int) {
    self->ui_grid = *((uint32_t*) value);
    self->send_settings_to_ui = true;
  }

  value = retrieve(handle, self->uris.ui_state_curs, &size, &type, &valflags);
  if (value
      && size == sizeof(LV2_Atom_Vector_Body) + sizeof(struct cursorstate)
      && type == self->uris.atom_Vector) {
    memcpy(&self->cursorstate, LV2_ATOM_BODY(value), sizeof(struct cursorstate));
    self->send_settings_to_ui = true;
  }

  value = retrieve(handle, self->uris.ui_state_trig, &size, &type, &valflags);
  if (value
      && size == sizeof(LV2_Atom_Vector_Body) + sizeof(struct triggerstate)
      && type == self->uris.atom_Vector) {
    memcpy(&self->triggerstate, LV2_ATOM_BODY(value), sizeof(struct triggerstate));
    self->send_settings_to_ui = true;
  }

  value = retrieve(handle, self->uris.ui_state_chn, &size, &type, &valflags);
  if (value
      && size == sizeof(LV2_Atom_Vector_Body) + self->n_channels * sizeof(struct channelstate)
      && type == self->uris.atom_Vector) {
    memcpy(self->channelstate, LV2_ATOM_BODY(value), self->n_channels * sizeof(struct channelstate));
    self->send_settings_to_ui = true;
  }

  value = retrieve(handle, self->uris.ui_state_misc, &size, &type, &valflags);
  if (value
      && size == sizeof(int32_t)
      && type == self->uris.atom_Int) {
    self->ui_misc = *((const int32_t*)value);
    self->send_settings_to_ui = true;
  }
  return LV2_STATE_SUCCESS;
}
Exemplo n.º 2
0
bool
lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
                uint32_t            frames,
                uint32_t            subframes,
                uint32_t            type,
                uint32_t            size,
                const uint8_t*      data)
{
	LV2_Event_Buffer*  ebuf;
	LV2_Event*         ev;
	LV2_Atom_Sequence* aseq;
	LV2_Atom_Event*    aev;
	switch (iter->evbuf->type) {
	case LV2_EVBUF_EVENT:
		ebuf = &iter->evbuf->buf.event;
		if (ebuf->capacity - ebuf->size < sizeof(LV2_Event) + size) {
			return false;
		}

		ev = (LV2_Event*)(ebuf->data + iter->offset);
		ev->frames    = frames;
		ev->subframes = subframes;
		ev->type      = type;
		ev->size      = size;
		memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);

		size               = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
		ebuf->size        += size;
		ebuf->event_count += 1;
		iter->offset      += size;
		break;
	case LV2_EVBUF_ATOM:
		aseq = (LV2_Atom_Sequence*)&iter->evbuf->buf.atom;
		if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size
		    < sizeof(LV2_Atom_Event) + size) {
			return false;
		}

		aev = (LV2_Atom_Event*)(
			(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
			+ iter->offset);
		aev->time.frames = frames;
		aev->body.type   = type;
		aev->body.size   = size;
		memcpy(LV2_ATOM_BODY(&aev->body), data, size);

		size             = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
		aseq->atom.size += size;
		iter->offset    += size;
		break;
	default:
		return false;
	}

	return true;
}
Exemplo n.º 3
0
Arquivo: lv2.c Projeto: aelse/setBfree
static void iowork(B3S* b3s, const LV2_Atom_Object* obj, int cmd) {
  const LV2_Atom* name = NULL;
  lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &name, 0);
  if (name) {
    struct worknfo w;
    w.cmd = cmd;
    w.status = -1;;
    strncpy(w.msg, (char *)LV2_ATOM_BODY(name), 1024);
    b3s->schedule->schedule_work(b3s->schedule->handle, sizeof(struct worknfo), &w);
  }
}
Exemplo n.º 4
0
bool
lv2_evbuf_get(LV2_Evbuf_Iterator iter,
              uint32_t*          frames,
              uint32_t*          subframes,
              uint32_t*          type,
              uint32_t*          size,
              uint8_t**          data)
{
    *frames = *subframes = *type = *size = 0;
    *data = NULL;

    if (!lv2_evbuf_is_valid(iter)) {
        return false;
    }

    LV2_Event_Buffer*  ebuf;
    LV2_Event*         ev;
    LV2_Atom_Sequence* aseq;
    LV2_Atom_Event*    aev;
    switch (iter.evbuf->type) {
    case LV2_EVBUF_EVENT:
        ebuf = &iter.evbuf->buf.event;
        ev = (LV2_Event*)((char*)ebuf->data + iter.offset);
        *frames    = ev->frames;
        *subframes = ev->subframes;
        *type      = ev->type;
        *size      = ev->size;
        *data      = (uint8_t*)ev + sizeof(LV2_Event);
        break;
    case LV2_EVBUF_ATOM:
        aseq = (LV2_Atom_Sequence*)&iter.evbuf->buf.atom;
        aev = (LV2_Atom_Event*)(
            (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
            + iter.offset);
        *frames    = aev->time.frames;
        *subframes = 0;
        *type      = aev->body.type;
        *size      = aev->body.size;
        *data      = LV2_ATOM_BODY(&aev->body);
        break;
    }

    return true;
}
Exemplo n.º 5
0
Arquivo: lv2.c Projeto: aelse/setBfree
static void advanced_config_set(B3S* b3s, const LV2_Atom_Object* obj) {
  const LV2_Atom* cfgline = NULL;
  lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &cfgline, 0);
  if (cfgline) {
    struct worknfo w;
    char* msg = (char *)LV2_ATOM_BODY(cfgline);
    if(!strcmp("special.reset=1", msg)) {
      w.cmd = CMD_RESET;
    }
    else if(!strcmp("special.reconfigure=1", msg)) {
      w.cmd = CMD_PURGE;
    }
    else {
      w.cmd = CMD_SETCFG;
    }
    w.status = -1;
    strncpy(w.msg, msg, 1024);
    b3s->schedule->schedule_work(b3s->schedule->handle, sizeof(struct worknfo), &w);
  }
}
Exemplo n.º 6
0
/**
* State restoration of the noise profile.
*/
static LV2_State_Status
restorestate(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
			 LV2_State_Handle handle, uint32_t flags,
			 const LV2_Feature *const *features)
{
	Nrepel *self = (Nrepel *)instance;
	size_t size;
	uint32_t type;
	uint32_t valflags;

	const int32_t *fftsize = retrieve(handle, self->prop_fftsize, &size, &type, &valflags);
	if (!fftsize || type != self->atom_Int || *fftsize != self->fft_size_2)
	{
		return LV2_STATE_ERR_NO_PROPERTY;
	}

	const void *vecFFTp2 = retrieve(handle, self->prop_FFTp2, &size, &type, &valflags);
	if (!vecFFTp2 || size != sizeof(FFTVector) || type != self->atom_Vector)
	{
		return LV2_STATE_ERR_NO_PROPERTY;
	}

	//Deactivate any denoising before loading any noise profile
	self->noise_thresholds_availables = false;

	//Copy to local variables
	memcpy(self->noise_thresholds_p2, (float *)LV2_ATOM_BODY(vecFFTp2), (self->fft_size_2 + 1) * sizeof(float));

	const float *wincount = retrieve(handle, self->prop_nwindow, &size, &type, &valflags);
	if (fftsize && type == self->atom_Float)
	{
		self->noise_window_count = *wincount;
	}

	//Reactivate denoising with restored profile
	self->noise_thresholds_availables = true;

	return LV2_STATE_SUCCESS;
}
Exemplo n.º 7
0
static void
run(LV2_Handle handle, uint32_t n_samples)
{
  SiSco* self = (SiSco*)handle;
  const uint32_t size = (sizeof(float) * n_samples + 80) * self->n_channels;
  const uint32_t capacity = self->notify->atom.size;
  bool capacity_ok = true;

  /* check if atom-port buffer is large enough to hold
   * all audio-samples and configuration settings */
  if (capacity < size + 216 + self->n_channels * 16) {
    capacity_ok = false;
    if (!self->printed_capacity_warning) {
      fprintf(stderr, "SiSco.lv2 error: LV2 comm-buffersize is insufficient %d/%d bytes.\n",
	  capacity, size + 216 + self->n_channels * 16);
      self->printed_capacity_warning = true;
    }
  }

  /* prepare forge buffer and initialize atom-sequence */
  lv2_atom_forge_set_buffer(&self->forge, (uint8_t*)self->notify, capacity);
  lv2_atom_forge_sequence_head(&self->forge, &self->frame, 0);

  /* Send settings to UI */
  if (self->send_settings_to_ui && self->ui_active) {
    self->send_settings_to_ui = false;
    /* forge container object of type 'ui_state' */
    LV2_Atom_Forge_Frame frame;
    lv2_atom_forge_frame_time(&self->forge, 0);
    x_forge_object(&self->forge, &frame, 1, self->uris.ui_state);
    /* forge attributes for 'ui_state' */
    lv2_atom_forge_property_head(&self->forge, self->uris.samplerate, 0);
    lv2_atom_forge_float(&self->forge, capacity_ok ? self->rate : 0);

    lv2_atom_forge_property_head(&self->forge, self->uris.ui_state_grid, 0);
    lv2_atom_forge_int(&self->forge, self->ui_grid);

    lv2_atom_forge_property_head(&self->forge, self->uris.ui_state_trig, 0);
    lv2_atom_forge_vector(&self->forge, sizeof(float), self->uris.atom_Float,
	sizeof(struct triggerstate) / sizeof(float), &self->triggerstate);

    lv2_atom_forge_property_head(&self->forge, self->uris.ui_state_curs, 0);
    lv2_atom_forge_vector(&self->forge, sizeof(int32_t), self->uris.atom_Int,
	sizeof(struct cursorstate) / sizeof(int32_t), &self->cursorstate);

    lv2_atom_forge_property_head(&self->forge, self->uris.ui_state_chn, 0);
    lv2_atom_forge_vector(&self->forge, sizeof(float), self->uris.atom_Float,
	self->n_channels * sizeof(struct channelstate) / sizeof(float), self->channelstate);

    lv2_atom_forge_property_head(&self->forge, self->uris.ui_state_misc, 0);
    lv2_atom_forge_int(&self->forge, self->ui_misc);

    /* close-off frame */
    lv2_atom_forge_pop(&self->forge, &frame);
  }

  /* Process incoming events from GUI */
  if (self->control) {
    LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(self->control)->body);
    /* for each message from UI... */
    while(!lv2_atom_sequence_is_end(&(self->control)->body, (self->control)->atom.size, ev)) {
      /* .. only look at atom-events.. */
      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;
	/* interpret atom-objects: */
	if (obj->body.otype == self->uris.ui_on) {
	  /* UI was activated */
	  self->ui_active = true;
	  self->send_settings_to_ui = true;
	} else if (obj->body.otype == self->uris.ui_off) {
	  /* UI was closed */
	  self->ui_active = false;
	} else if (obj->body.otype == self->uris.ui_state) {
	  /* UI sends current settings */
	  const LV2_Atom* grid = NULL;
	  const LV2_Atom* trig = NULL;
	  const LV2_Atom* curs = NULL;
	  const LV2_Atom* misc = NULL;
	  const LV2_Atom* chn = NULL;
	  lv2_atom_object_get(obj,
	      self->uris.ui_state_grid, &grid,
	      self->uris.ui_state_trig, &trig,
	      self->uris.ui_state_curs, &curs,
	      self->uris.ui_state_misc, &misc,
	      self->uris.ui_state_chn, &chn,
	      0);
	  if (grid && grid->type == self->uris.atom_Int) {
	    self->ui_grid = ((LV2_Atom_Int*)grid)->body;
	  }
	  if (misc && misc->type == self->uris.atom_Int) {
	    self->ui_misc = ((LV2_Atom_Int*)misc)->body;
	  }
	  if (trig && trig->type == self->uris.atom_Vector) {
	    LV2_Atom_Vector *vof = (LV2_Atom_Vector*)LV2_ATOM_BODY(trig);
	    if (vof->atom.type == self->uris.atom_Float) {
	      struct triggerstate *ts = (struct triggerstate *) LV2_ATOM_BODY(&vof->atom);
	      memcpy(&self->triggerstate, ts, sizeof(struct triggerstate));
	    }
	  }
	  if (curs && curs->type == self->uris.atom_Vector) {
	    LV2_Atom_Vector *vof = (LV2_Atom_Vector*)LV2_ATOM_BODY(curs);
	    if (vof->atom.type == self->uris.atom_Int) {
	      struct cursorstate *cs = (struct cursorstate *) LV2_ATOM_BODY(&vof->atom);
	      memcpy(&self->cursorstate, cs, sizeof(struct cursorstate));
	    }
	  }
	  if (chn && chn->type == self->uris.atom_Vector) {
	    LV2_Atom_Vector *vof = (LV2_Atom_Vector*)LV2_ATOM_BODY(chn);
	    if (vof->atom.type == self->uris.atom_Float) {
	      struct channelstate *cs = (struct channelstate *) LV2_ATOM_BODY(&vof->atom);
	      memcpy(self->channelstate, cs, self->n_channels * sizeof(struct channelstate));
	    }
	  }
	}
      }
      ev = lv2_atom_sequence_next(ev);
    }
  }

  /* process audio data */
  for (uint32_t c = 0; c < self->n_channels; ++c) {
    if (self->ui_active && capacity_ok) {
      /* if UI is active, send raw audio data to UI */
      tx_rawaudio(&self->forge, &self->uris, c, n_samples, self->input[c]);
    }
    /* if not processing in-place, forward audio */
    if (self->input[c] != self->output[c]) {
      memcpy(self->output[c], self->input[c], sizeof(float) * n_samples);
    }
  }

  /* close off atom-sequence */
  lv2_atom_forge_pop(&self->forge, &self->frame);
}
Exemplo n.º 8
0
static void
port_event(LV2UI_Handle handle,
           uint32_t     port_index,
           uint32_t     buffer_size,
           uint32_t     format,
           const void*  buffer)
{
	SFSUI* ui = (SFSUI*)handle;
	LV2_Atom* atom = (LV2_Atom*)buffer;
	if (format == ui->uris.atom_eventTransfer
			&& (atom->type == ui->uris.atom_Blank|| atom->type == ui->uris.atom_Object))
	{
		/* cast the buffer to Atom Object */
		LV2_Atom_Object* obj = (LV2_Atom_Object*)atom;
		LV2_Atom *a0 = NULL;
		LV2_Atom *a1 = NULL;
		if (obj->body.otype == ui->uris.rawstereo
				&& 2 == lv2_atom_object_get(obj, ui->uris.audioleft, &a0, ui->uris.audioright, &a1, NULL)
				&& a0 && a1
				&& a0->type == ui->uris.atom_Vector
				&& a1->type == ui->uris.atom_Vector
			 )
		{
			LV2_Atom_Vector* left = (LV2_Atom_Vector*)LV2_ATOM_BODY(a0);
			LV2_Atom_Vector* right = (LV2_Atom_Vector*)LV2_ATOM_BODY(a1);
			if (left->atom.type == ui->uris.atom_Float && right->atom.type == ui->uris.atom_Float) {
				const size_t n_elem = (a0->size - sizeof(LV2_Atom_Vector_Body)) / left->atom.size;
				const float *l = (float*) LV2_ATOM_BODY(&left->atom);
				const float *r = (float*) LV2_ATOM_BODY(&right->atom);
				process_audio(ui, n_elem, l, r);
			}
		}
		else if (
				/* handle 'state/settings' data object */
				obj->body.otype == ui->uris.ui_state
				/* retrieve properties from object and
				 * check that there the [here] three required properties are set.. */
				&& 1 == lv2_atom_object_get(obj,
					ui->uris.samplerate, &a0, NULL)
				/* ..and non-null.. */
				&& a0
				/* ..and match the expected type */
				&& a0->type == ui->uris.atom_Float
				)
		{
			ui->rate = ((LV2_Atom_Float*)a0)->body;
			reinitialize_fft(ui, ui->fft_bins);
		}
	}
	else if (format != 0) return;

	if (port_index == SS_FFT) {
		float val = *(float *)buffer;
		uint32_t fft_bins = floorf(val / 2.0);
		if (ui->fft_bins != fft_bins) {
			reinitialize_fft(ui, fft_bins);
			robtk_select_set_value(ui->sel_fft, ui->fft_bins);
		}
	}
	else if (port_index == SS_BAND) {
		float val = *(float *)buffer;
		ui->disable_signals = true;
		robtk_cbtn_set_active(ui->btn_oct, val != 0);
		ui->disable_signals = false;
	}
	else if (port_index == SS_SCREEN) {
		ui->disable_signals = true;
		robtk_dial_set_value(ui->screen, *(float *)buffer);
		ui->disable_signals = false;
	}
}
Exemplo n.º 9
0
Arquivo: lv2.c Projeto: aelse/setBfree
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);
  }
}
Exemplo n.º 10
0
// rt
static void
_message_cb(const char *path, const char *fmt, const LV2_Atom_Tuple *body,
	void *data)
{
	prog_t *handle = data;

	osc_data_t *ptr = handle->osc_ptr;
	const osc_data_t *end = handle->osc_end;

	osc_data_t *itm = NULL;
	if(handle->bndl_cnt)
		ptr = osc_start_bundle_item(ptr, end, &itm);

	ptr = osc_set_path(ptr, end, path);
	ptr = osc_set_fmt(ptr, end, fmt);

	const LV2_Atom *itr = lv2_atom_tuple_begin(body);
	for(const char *type = fmt;
		*type && !lv2_atom_tuple_is_end(LV2_ATOM_BODY(body), body->atom.size, itr);
		type++, itr = lv2_atom_tuple_next(itr))
	{
		switch(*type)
		{
			case 'i':
			{
				ptr = osc_set_int32(ptr, end, ((const LV2_Atom_Int *)itr)->body);
				break;
			}
			case 'f':
			{
				ptr = osc_set_float(ptr, end, ((const LV2_Atom_Float *)itr)->body);
				break;
			}
			case 's':
			case 'S':
			{
				ptr = osc_set_string(ptr, end, LV2_ATOM_BODY_CONST(itr));
				break;
			}
			case 'b':
			{
				ptr = osc_set_blob(ptr, end, itr->size, LV2_ATOM_BODY(itr));
				break;
			}

			case 'h':
			{
				ptr = osc_set_int64(ptr, end, ((const LV2_Atom_Long *)itr)->body);
				break;
			}
			case 'd':
			{
				ptr = osc_set_double(ptr, end, ((const LV2_Atom_Double *)itr)->body);
				break;
			}
			case 't':
			{
				ptr = osc_set_timetag(ptr, end, ((const LV2_Atom_Long *)itr)->body);
				break;
			}

			case 'T':
			case 'F':
			case 'N':
			case 'I':
			{
				break;
			}

			case 'c':
			{
				ptr = osc_set_char(ptr, end, ((const LV2_Atom_Int *)itr)->body);
				break;
			}
			case 'm':
			{
				const uint8_t *src = LV2_ATOM_BODY_CONST(itr);
				const uint8_t dst [4] = {
					0x00, // port byte
					itr->size >= 1 ? src[0] : 0x00,
					itr->size >= 2 ? src[1] : 0x00,
					itr->size >= 3 ? src[2] : 0x00
				};
				ptr = osc_set_midi(ptr, end, dst);
				break;
			}
		}
	}
	
	if(handle->bndl_cnt)
		ptr = osc_end_bundle_item(ptr, end, itm);

	handle->osc_ptr = ptr;
}
Exemplo n.º 11
0
SRATOM_API
int
sratom_write(Sratom*         sratom,
             LV2_URID_Unmap* unmap,
             uint32_t        flags,
             const SerdNode* subject,
             const SerdNode* predicate,
             uint32_t        type_urid,
             uint32_t        size,
             const void*     body)
{
	const char* const type        = unmap->unmap(unmap->handle, type_urid);
	uint8_t           idbuf[12]   = "b0000000000";
	SerdNode          id          = serd_node_from_string(SERD_BLANK, idbuf);
	uint8_t           nodebuf[12] = "b0000000000";
	SerdNode          node        = serd_node_from_string(SERD_BLANK, nodebuf);
	SerdNode          object      = SERD_NODE_NULL;
	SerdNode          datatype    = SERD_NODE_NULL;
	SerdNode          language    = SERD_NODE_NULL;
	bool              new_node    = false;
	if (type_urid == 0 && size == 0) {
		object = serd_node_from_string(SERD_URI, USTR(NS_RDF "nil"));
	} else if (type_urid == sratom->forge.String) {
		object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body);
	} else if (type_urid == sratom->forge.Chunk) {
		datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary");
		object   = serd_node_new_blob(body, size, true);
		new_node = true;
	} else if (type_urid == sratom->forge.Literal) {
		const LV2_Atom_Literal_Body* lit = (const LV2_Atom_Literal_Body*)body;
		const uint8_t*         str = USTR(lit + 1);
		object = serd_node_from_string(SERD_LITERAL, str);
		if (lit->datatype) {
			datatype = serd_node_from_string(
				SERD_URI, USTR(unmap->unmap(unmap->handle, lit->datatype)));
		} else if (lit->lang) {
			const char*  lang       = unmap->unmap(unmap->handle, lit->lang);
			const char*  prefix     = "http://lexvo.org/id/iso639-3/";
			const size_t prefix_len = strlen(prefix);
			if (lang && !strncmp(lang, prefix, prefix_len)) {
				language = serd_node_from_string(
					SERD_LITERAL, USTR(lang + prefix_len));
			} else {
				fprintf(stderr, "Unknown language URID %d\n", lit->lang);
			}
		}
	} else if (type_urid == sratom->forge.URID) {
		const uint32_t urid = *(const uint32_t*)body;
		const uint8_t* str  = USTR(unmap->unmap(unmap->handle, urid));
		object = serd_node_from_string(SERD_URI, str);
	} else if (type_urid == sratom->forge.Path) {
		const uint8_t* str = USTR(body);
		if (path_is_absolute((const char*)str)) {
			new_node = true;
			object   = serd_node_new_file_uri(str, NULL, NULL, false);
		} else {
			SerdURI base_uri = SERD_URI_NULL;
			if (!sratom->base_uri.buf ||
			    strncmp((const char*)sratom->base_uri.buf, "file://", 7)) {
				fprintf(stderr, "warning: Relative path but base is not a file URI.\n");
				fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n");
				object   = serd_node_from_string(SERD_LITERAL, str);
				datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path));
			} else {
				if (sratom->base_uri.buf) {
					serd_uri_parse(sratom->base_uri.buf, &base_uri);
				}
				new_node = true;
				SerdNode rel = serd_node_new_file_uri(str, NULL, NULL, false);
				object = serd_node_new_uri_from_node(&rel, &base_uri, NULL);
				serd_node_free(&rel);
			}
		}
	} else if (type_urid == sratom->forge.URI) {
		const uint8_t* str = USTR(body);
		object = serd_node_from_string(SERD_URI, str);
	} else if (type_urid == sratom->forge.Int) {
		new_node = true;
		object   = serd_node_new_integer(*(const int32_t*)body);
		datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
		                                 ? NS_XSD "integer" : NS_XSD "int");
	} else if (type_urid == sratom->forge.Long) {
		new_node = true;
		object   = serd_node_new_integer(*(const int64_t*)body);
		datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
		                                 ? NS_XSD "integer" : NS_XSD "long");
	} else if (type_urid == sratom->forge.Float) {
		new_node = true;
		object   = serd_node_new_decimal(*(const float*)body, 8);
		datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
		                                 ? NS_XSD "decimal" : NS_XSD "float");
	} else if (type_urid == sratom->forge.Double) {
		new_node = true;
		object   = serd_node_new_decimal(*(const double*)body, 16);
		datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
		                                 ? NS_XSD "decimal" : NS_XSD "double");
	} else if (type_urid == sratom->forge.Bool) {
		const int32_t val = *(const int32_t*)body;
		datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean");
		object   = serd_node_from_string(SERD_LITERAL,
		                                 USTR(val ? "true" : "false"));
	} else if (type_urid == sratom->midi_MidiEvent) {
		new_node = true;
		datatype = serd_node_from_string(SERD_URI, USTR(LV2_MIDI__MidiEvent));
		uint8_t* str = (uint8_t*)calloc(size * 2 + 1, 1);
		for (uint32_t i = 0; i < size; ++i) {
			snprintf((char*)str + (2 * i), size * 2 + 1, "%02X",
			         (unsigned)(uint8_t)*((const uint8_t*)body + i));
		}
		object = serd_node_from_string(SERD_LITERAL, USTR(str));
	} else if (type_urid == sratom->atom_Event) {
		const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body;
		gensym(&id, 'e', sratom->next_id++);
		start_object(sratom, &flags, subject, predicate, &id, NULL);
		// TODO: beat time
		SerdNode time = serd_node_new_integer(ev->time.frames);
		SerdNode p    = serd_node_from_string(SERD_URI,
		                                      USTR(LV2_ATOM__frameTime));
		datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal");
		sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL,
		                        &id, &p, &time, &datatype, &language);
		serd_node_free(&time);

		p = serd_node_from_string(SERD_URI, NS_RDF "value");
		sratom_write(sratom, unmap, SERD_ANON_CONT, &id, &p,
		             ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body));
		if (sratom->end_anon) {
			sratom->end_anon(sratom->handle, &id);
		}
	} else if (type_urid == sratom->forge.Tuple) {
		gensym(&id, 't', sratom->next_id++);
		start_object(sratom, &flags, subject, predicate, &id, type);
		SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value");
		flags |= SERD_LIST_O_BEGIN;
		LV2_ATOM_TUPLE_BODY_FOREACH(body, size, i) {
			list_append(sratom, unmap, &flags, &id, &p, &node,
			            i->size, i->type, LV2_ATOM_BODY(i));
		}
Exemplo n.º 12
0
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");
	}
}
Exemplo n.º 13
0
static LilvState*
new_state_from_model(LilvWorld*       world,
                     LV2_URID_Map*    map,
                     SordModel*       model,
                     const SordNode*  node,
                     const char*      dir)
{
	LilvState* const state = (LilvState*)malloc(sizeof(LilvState));
	memset(state, '\0', sizeof(LilvState));
	state->dir       = lilv_strdup(dir);
	state->atom_Path = map->map(map->handle, LV2_ATOM__Path);

	// Get the plugin URI this state applies to
	SordIter* i = sord_search(model, node, world->uris.lv2_appliesTo, 0, 0);
	if (i) {
		const SordNode* object = sord_iter_get_node(i, SORD_OBJECT);
		const SordNode* graph  = sord_iter_get_node(i, SORD_GRAPH);
		state->plugin_uri = lilv_node_new_from_node(world, object);
		if (!state->dir && graph) {
			state->dir = lilv_strdup((const char*)sord_node_get_string(graph));
		}
		sord_iter_free(i);
	} else if (sord_ask(model,
	                    node,
	                    world->uris.rdf_a,
	                    world->uris.lv2_Plugin, 0)) {
		// Loading plugin description as state (default state)
		state->plugin_uri = lilv_node_new_from_node(world, node);
	} else {
		LILV_ERRORF("State %s missing lv2:appliesTo property\n",
		            sord_node_get_string(node));
	}

	// Get the state label
	i = sord_search(model, node, world->uris.rdfs_label, NULL, NULL);
	if (i) {
		const SordNode* object = sord_iter_get_node(i, SORD_OBJECT);
		const SordNode* graph  = sord_iter_get_node(i, SORD_GRAPH);
		state->label = lilv_strdup((const char*)sord_node_get_string(object));
		if (!state->dir) {
			state->dir = lilv_strdup((const char*)sord_node_get_string(graph));
		}
		sord_iter_free(i);
	}

	Sratom*        sratom = sratom_new(map);
	SerdChunk      chunk  = { NULL, 0 };
	LV2_Atom_Forge forge;
	lv2_atom_forge_init(&forge, map);
	lv2_atom_forge_set_sink(
		&forge, sratom_forge_sink, sratom_forge_deref, &chunk);

	// Get port values
	SordIter* ports = sord_search(model, node, world->uris.lv2_port, 0, 0);
	FOREACH_MATCH(ports) {
		const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT);

		SordNode* label  = sord_get(model, port, world->uris.rdfs_label, 0, 0);
		SordNode* symbol = sord_get(model, port, world->uris.lv2_symbol, 0, 0);
		SordNode* value  = sord_get(model, port, world->uris.pset_value, 0, 0);
		if (!value) {
			value = sord_get(model, port, world->uris.lv2_default, 0, 0);
		}
		if (!symbol) {
			LILV_ERRORF("State `%s' port missing symbol.\n",
			            sord_node_get_string(node));
		} else if (value) {
			chunk.len = 0;
			sratom_read(sratom, &forge, world->world, model, value);
			LV2_Atom* atom = (LV2_Atom*)chunk.buf;

			append_port_value(state,
			                  (const char*)sord_node_get_string(symbol),
			                  LV2_ATOM_BODY(atom), atom->size, atom->type);

			if (label) {
				lilv_state_set_label(state,
				                     (const char*)sord_node_get_string(label));
			}
		}
		sord_node_free(world->world, value);
		sord_node_free(world->world, symbol);
		sord_node_free(world->world, label);
	}
	sord_iter_free(ports);

	// Get properties
	SordNode* statep     = sord_new_uri(world->world, USTR(LV2_STATE__state));
	SordNode* state_node = sord_get(model, node, statep, NULL, NULL);
	if (state_node) {
		SordIter* props = sord_search(model, state_node, 0, 0, 0);
		FOREACH_MATCH(props) {
			const SordNode* p = sord_iter_get_node(props, SORD_PREDICATE);
			const SordNode* o = sord_iter_get_node(props, SORD_OBJECT);

			chunk.len = 0;
			lv2_atom_forge_set_sink(
				&forge, sratom_forge_sink, sratom_forge_deref, &chunk);

			sratom_read(sratom, &forge, world->world, model, o);
			LV2_Atom* atom  = (LV2_Atom*)chunk.buf;
			uint32_t  flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE;
			Property  prop  = { NULL, 0, 0, 0, flags };

			prop.key   = map->map(map->handle, (const char*)sord_node_get_string(p));
			prop.type  = atom->type;
			prop.size  = atom->size;
			prop.value = malloc(atom->size);
			memcpy(prop.value, LV2_ATOM_BODY(atom), atom->size);
			if (atom->type == forge.Path) {
				prop.flags = LV2_STATE_IS_PORTABLE;
			}

			if (prop.value) {
				state->props = (Property*)realloc(
					state->props, (++state->num_props) * sizeof(Property));
				state->props[state->num_props - 1] = prop;
			}
		}
		sord_iter_free(props);
	}
	sord_node_free(world->world, state_node);
	sord_node_free(world->world, statep);

	free((void*)chunk.buf);
	sratom_free(sratom);

	qsort(state->props, state->num_props, sizeof(Property), property_cmp);
	qsort(state->values, state->num_values, sizeof(PortValue), value_cmp);

	return state;
}
Exemplo n.º 14
0
    void lv2_run(const uint32_t sampleCount)
    {
        // cache midi input and time position first
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
        uint32_t midiEventCount = 0;
#endif

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS
        LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
        {
            if (event == nullptr)
                break;

# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
            if (event->body.type == fURIDs.midiEvent)
            {
                if (midiEventCount >= kMaxMidiEvents)
                    continue;

                const uint8_t* const data((const uint8_t*)(event + 1));

                MidiEvent& midiEvent(fMidiEvents[midiEventCount++]);

                midiEvent.frame = event->time.frames;
                midiEvent.size  = event->body.size;

                if (midiEvent.size > MidiEvent::kDataSize)
                {
                    midiEvent.dataExt = data;
                    std::memset(midiEvent.data, 0, MidiEvent::kDataSize);
                }
                else
                {
                    midiEvent.dataExt = nullptr;
                    std::memcpy(midiEvent.data, data, midiEvent.size);
                }

                continue;
            }
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
            if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject)
            {
                const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body);

                if (obj->body.otype != fURIDs.timePosition)
                    continue;

                LV2_Atom* bar     = nullptr;
                LV2_Atom* barBeat = nullptr;
                LV2_Atom* beatUnit = nullptr;
                LV2_Atom* beatsPerBar = nullptr;
                LV2_Atom* beatsPerMinute = nullptr;
                LV2_Atom* frame = nullptr;
                LV2_Atom* speed = nullptr;
                LV2_Atom* ticksPerBeat = nullptr;

                lv2_atom_object_get(obj,
                                    fURIDs.timeBar, &bar,
                                    fURIDs.timeBarBeat, &barBeat,
                                    fURIDs.timeBeatUnit, &beatUnit,
                                    fURIDs.timeBeatsPerBar, &beatsPerBar,
                                    fURIDs.timeBeatsPerMinute, &beatsPerMinute,
                                    fURIDs.timeFrame, &frame,
                                    fURIDs.timeSpeed, &speed,
                                    fURIDs.timeTicksPerBeat, &ticksPerBeat,
                                    nullptr);

                // need to handle this first as other values depend on it
                if (ticksPerBeat != nullptr)
                {
                    /**/ if (ticksPerBeat->type == fURIDs.atomDouble)
                        fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
                    else if (ticksPerBeat->type == fURIDs.atomFloat)
                        fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
                    else if (ticksPerBeat->type == fURIDs.atomInt)
                        fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
                    else if (ticksPerBeat->type == fURIDs.atomLong)
                        fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
                    else
                        d_stderr("Unknown lv2 ticksPerBeat value type");

                    if (fLastPositionData.ticksPerBeat > 0)
                        fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat;
                }

                // same
                if (speed != nullptr)
                {
                    /**/ if (speed->type == fURIDs.atomDouble)
                        fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
                    else if (speed->type == fURIDs.atomFloat)
                        fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
                    else if (speed->type == fURIDs.atomInt)
                        fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body;
                    else if (speed->type == fURIDs.atomLong)
                        fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body;
                    else
                        d_stderr("Unknown lv2 speed value type");

                    fTimePosition.playing = d_isNotZero(fLastPositionData.speed);
                }

                if (bar != nullptr)
                {
                    /**/ if (bar->type == fURIDs.atomDouble)
                        fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body;
                    else if (bar->type == fURIDs.atomFloat)
                        fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body;
                    else if (bar->type == fURIDs.atomInt)
                        fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body;
                    else if (bar->type == fURIDs.atomLong)
                        fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body;
                    else
                        d_stderr("Unknown lv2 bar value type");

                    if (fLastPositionData.bar >= 0)
                        fTimePosition.bbt.bar = fLastPositionData.bar + 1;
                }

                if (barBeat != nullptr)
                {
                    /**/ if (barBeat->type == fURIDs.atomDouble)
                        fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body;
                    else if (barBeat->type == fURIDs.atomFloat)
                        fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body;
                    else if (barBeat->type == fURIDs.atomInt)
                        fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body;
                    else if (barBeat->type == fURIDs.atomLong)
                        fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body;
                    else
                        d_stderr("Unknown lv2 barBeat value type");

                    if (fLastPositionData.barBeat >= 0.0f)
                    {
                        const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
                        fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
                        fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
                    }
                }

                if (beatUnit != nullptr)
                {
                    /**/ if (beatUnit->type == fURIDs.atomDouble)
                        fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body;
                    else if (beatUnit->type == fURIDs.atomFloat)
                        fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body;
                    else if (beatUnit->type == fURIDs.atomInt)
                        fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body;
                    else if (beatUnit->type == fURIDs.atomLong)
                        fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body;
                    else
                        d_stderr("Unknown lv2 beatUnit value type");

                    if (fLastPositionData.beatUnit > 0)
                        fTimePosition.bbt.beatType = fLastPositionData.beatUnit;
                }

                if (beatsPerBar != nullptr)
                {
                    /**/ if (beatsPerBar->type == fURIDs.atomDouble)
                        fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
                    else if (beatsPerBar->type == fURIDs.atomFloat)
                        fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
                    else if (beatsPerBar->type == fURIDs.atomInt)
                        fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
                    else if (beatsPerBar->type == fURIDs.atomLong)
                        fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
                    else
                        d_stderr("Unknown lv2 beatsPerBar value type");

                    if (fLastPositionData.beatsPerBar > 0.0f)
                        fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar;
                }

                if (beatsPerMinute != nullptr)
                {
                    /**/ if (beatsPerMinute->type == fURIDs.atomDouble)
                        fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
                    else if (beatsPerMinute->type == fURIDs.atomFloat)
                        fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
                    else if (beatsPerMinute->type == fURIDs.atomInt)
                        fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
                    else if (beatsPerMinute->type == fURIDs.atomLong)
                        fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
                    else
                        d_stderr("Unknown lv2 beatsPerMinute value type");

                    if (fLastPositionData.beatsPerMinute > 0.0f)
                    {
                        fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute;

                        if (d_isNotZero(fLastPositionData.speed))
                            fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed);
                    }
                }

                if (frame != nullptr)
                {
                    /**/ if (frame->type == fURIDs.atomDouble)
                        fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body;
                    else if (frame->type == fURIDs.atomFloat)
                        fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body;
                    else if (frame->type == fURIDs.atomInt)
                        fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body;
                    else if (frame->type == fURIDs.atomLong)
                        fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body;
                    else
                        d_stderr("Unknown lv2 frame value type");

                    if (fLastPositionData.frame >= 0)
                        fTimePosition.frame = fLastPositionData.frame;
                }

                fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
                                                 fTimePosition.bbt.beatsPerBar*
                                                 (fTimePosition.bbt.bar-1);

                fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 &&
                                           fLastPositionData.beatUnit > 0 &&
                                           fLastPositionData.beatsPerBar > 0.0f);

                fPlugin.setTimePosition(fTimePosition);

                continue;
            }
# endif
        }
#endif

        // check for messages from UI
#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI
        LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
        {
            if (event == nullptr)
                break;

            if (event->body.type == fURIDs.distrhoState && fWorker != nullptr)
            {
                const void* const data((const void*)(event + 1));

                // check if this is our special message
                if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0)
                {
                    for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
                        fNeededUiSends[i] = true;
                }
                else
                // no, send to DSP as usual
                {
                    fWorker->schedule_work(fWorker->handle, event->body.size, data);
                }
            }
        }
#endif

        // Check for updated parameters
        float curValue;

        for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
        {
            if (fPortControls[i] == nullptr)
                continue;

            curValue = *fPortControls[i];

            if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
            {
                fLastControlValues[i] = curValue;
                fPlugin.setParameterValue(i, curValue);
            }
        }

        // Run plugin
        if (sampleCount != 0)
        {
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
            fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount);
#else
            fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
            // update timePos for next callback
            if (d_isNotZero(fLastPositionData.speed))
            {
                if (fLastPositionData.speed > 0.0)
                {
                    // playing forwards
                    fLastPositionData.frame += sampleCount;
                }
                else
                {
                    // playing backwards
                    fLastPositionData.frame -= sampleCount;

                    if (fLastPositionData.frame < 0)
                        fLastPositionData.frame = 0;
                }

                fTimePosition.frame = fLastPositionData.frame;

                if (fTimePosition.bbt.valid)
                {
                    const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
                    const double framesPerBeat  = 60.0 * fSampleRate / beatsPerMinute;
                    const double addedBarBeats  = double(sampleCount) / framesPerBeat;

                    if (fLastPositionData.barBeat >= 0.0f)
                    {
                        fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats,
                                                              fLastPositionData.beatsPerBar);

                        const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
                        fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
                        fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;

                        if (fLastPositionData.bar >= 0)
                        {
                            fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/
                                                             fLastPositionData.beatsPerBar);

                            if (fLastPositionData.bar < 0)
                                fLastPositionData.bar = 0;

                            fTimePosition.bbt.bar = fLastPositionData.bar + 1;

                            fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
                                                             fTimePosition.bbt.beatsPerBar*
                                                            (fTimePosition.bbt.bar-1);
                        }
                    }

                    fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute);
                }
            }
#endif
        }

        updateParameterOutputs();

#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI
        const uint32_t capacity = fPortEventsOut->atom.size;

        bool needsInit = true;
        uint32_t size, offset = 0;
        LV2_Atom_Event* aev;

        // TODO - MIDI Output

        for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
        {
            if (! fNeededUiSends[i])
                continue;

            const String& key = fPlugin.getStateKey(i);

            for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit)
            {
                const String& curKey = cit->first;

                if (curKey != key)
                    continue;

                const String& value = cit->second;

                // set msg size (key + value + separator + 2x null terminator)
                const size_t msgSize(key.length()+value.length()+3);

                if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset)
                    break;

                if (needsInit)
                {
                    fPortEventsOut->atom.size = 0;
                    fPortEventsOut->atom.type = fURIDs.atomSequence;
                    fPortEventsOut->body.unit = 0;
                    fPortEventsOut->body.pad  = 0;
                    needsInit = false;
                }

                // reserve msg space
                char msgBuf[msgSize];
                std::memset(msgBuf, 0, msgSize);

                // write key and value in atom bufer
                std::memcpy(msgBuf, key.buffer(), key.length());
                std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length());

                // put data
                aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fPortEventsOut) + offset);
                aev->time.frames = 0;
                aev->body.type   = fURIDs.distrhoState;
                aev->body.size   = msgSize;
                std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize-1);

                size    = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize);
                offset += size;
                fPortEventsOut->atom.size += size;

                fNeededUiSends[i] = false;
                break;
            }
        }
#endif
    }