#ifdef HAVE_LILV_0_16_0
// Load default state
+ if (_worker) {
+ /* immediately schedule any work,
+ * so that state restore later will not find a busy
+ * worker. latency_compute_run() flushes any replies
+ */
+ _worker->set_synchronous(true);
+ }
LilvState* state = lilv_state_new_from_world(
_world.world, _uri_map.urid_map(), lilv_plugin_get_uri(_impl->plugin));
if (state && _has_state_interface) {
case 15: h.x0 = 13; h.x1 = 14; h.y0 = 0; h.y1 = 1; break; // Gain H
case 22: h.x0 = 13; h.x1 = 14; h.y0 = 5; h.y1 = 6; break; // enable H
-
- case 16: h.x0 = 14; h.x1 = 15; h.y0 = 4; h.y1 = 6; break; // Master Gain
+ case 16: h.x0 = 14; h.x1 = 15; h.y0 = 1; h.y1 = 3; break; // Master Gain
+ case 23: h.x0 = 14; h.x1 = 15; h.y0 = 5; h.y1 = 6; break; // Master Enable
default:
return false;
}
LV2_Worker_Schedule schedule = { _state_worker, work_schedule };
const LV2_Feature state_sched_feature = { LV2_WORKER__schedule, &schedule };
if (_state_worker) {
- state_features[1] = &state_sched_feature;
+ state_features[0] = &state_sched_feature;
}
if (state) {
const TempoMetric& t,
Timecode::BBT_Time& bbt,
double speed,
+ double bpm,
framepos_t position,
framecnt_t offset)
{
lv2_atom_forge_key(forge, urids.time_beatsPerBar);
lv2_atom_forge_float(forge, t.meter().divisions_per_bar());
lv2_atom_forge_key(forge, urids.time_beatsPerMinute);
- lv2_atom_forge_float(forge, t.tempo().beats_per_minute());
+ lv2_atom_forge_float(forge, bpm);
#else
lv2_atom_forge_blank(forge, &frame, 1, urids.time_Position);
lv2_atom_forge_property_head(forge, urids.time_frame, 0);
lv2_atom_forge_property_head(forge, urids.time_beatsPerBar, 0);
lv2_atom_forge_float(forge, t.meter().divisions_per_bar());
lv2_atom_forge_property_head(forge, urids.time_beatsPerMinute, 0);
- lv2_atom_forge_float(forge, t.tempo().beats_per_minute());
+ lv2_atom_forge_float(forge, bpm);
#endif
LV2_Evbuf_Iterator end = lv2_evbuf_end(buf);
}
if (_bpm_control_port) {
- *_bpm_control_port = tmetric.tempo().beats_per_minute();
+ *_bpm_control_port = tmap.tempo_at_frame (start).beats_per_minute();
}
#ifdef LV2_EXTENDED
}
if (valid && (flags & PORT_INPUT)) {
- Timecode::BBT_Time bbt;
if ((flags & PORT_POSITION)) {
+ Timecode::BBT_Time bbt (tmap.bbt_at_frame (start));
+ double bpm = tmap.tempo_at_frame (start).beats_per_minute();
+ double beatpos = (bbt.bars - 1) * tmetric.meter().divisions_per_bar()
+ + (bbt.beats - 1)
+ + (bbt.ticks / Timecode::BBT_Time::ticks_per_beat);
+ beatpos *= tmetric.meter().note_divisor() / 4.0;
if (start != _next_cycle_start ||
- speed != _next_cycle_speed) {
- // Transport has changed, write position at cycle start
- bbt = tmap.bbt_at_frame (start);
+ speed != _next_cycle_speed ||
+ rint (1000 * beatpos) != rint(1000 * _next_cycle_beat) ||
+ bpm != _current_bpm) {
+ // Transport or Tempo has changed, write position at cycle start
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, speed, start, 0);
+ tmetric, bbt, speed, bpm, start, 0);
}
}
++m;
} else {
tmetric.set_metric(metric);
+ Timecode::BBT_Time bbt;
bbt = tmap.bbt_at_pulse (metric->pulse());
+ double bpm = tmap.tempo_at_frame (start/*XXX*/).beats_per_minute();
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, speed,
+ tmetric, bbt, speed, bpm,
metric->frame(),
metric->frame() - start);
++metric_i;
_next_cycle_speed = speed;
_next_cycle_start = end;
+ {
+ /* keep track of lv2:timePosition like plugins can do.
+ * Note: for no-midi plugins, we only ever send information at cycle-start,
+ * so it needs to be realative to that.
+ */
+ TempoMetric t = tmap.metric_at(start);
+ _current_bpm = tmap.tempo_at_frame (start).beats_per_minute();
+ Timecode::BBT_Time bbt (tmap.bbt_at_frame (start));
+ double beatpos = (bbt.bars - 1) * t.meter().divisions_per_bar()
+ + (bbt.beats - 1)
+ + (bbt.ticks / Timecode::BBT_Time::ticks_per_beat);
+ beatpos *= tmetric.meter().note_divisor() / 4.0;
+ _next_cycle_beat = beatpos + nframes * speed * _current_bpm / (60.f * _session.frame_rate());
+ }
+
if (_latency_control_port) {
framecnt_t new_latency = signal_latency ();
_current_latency = new_latency;
}
void
-LV2Plugin::run(pframes_t nframes)
+LV2Plugin::run(pframes_t nframes, bool sync_work)
{
uint32_t const N = parameter_count();
for (uint32_t i = 0; i < N; ++i) {
if (_worker) {
// Execute work synchronously if we're freewheeling (export)
- _worker->set_synchronous(session().engine().freewheeling());
+ _worker->set_synchronous(sync_work || session().engine().freewheeling());
}
// Run the plugin for this cycle
port_index++;
}
- run(bufsize);
+ run(bufsize, true);
deactivate();
if (was_activated) {
activate();