When bouncing Region or Range, Session::write_one_track()
blocks processing, but takes no process-lock.
It is possible that a latency-callback arrives at the same
time while Route::bounce_process is active and calls ::run.
This can trigger a delayline.cc Assertion `lm.locked ()' failed
in either thread.
Now latency-callbacks are postponed until the session can
process normally again
process_index should not be compared/combined with expected_end_sample, since
the former is a process-cycle count and the latter is a timeline position.
* first the region is scanned for bpm and one-shot status
* then we handle properties that should be applied from a drag&drop
* then we handle the existing arrangement-style slot properties that should persist
This addresses the issue described in 83719fba1a.
First process all queued self_delete() requests before scheduling
Editor::redisplay_track_views() which uses PRIORITY_DEFAULT.
THe length of a Source(File) is always measured from its start. In this sense,
the length is like a position on the timeline, which is a duration with an
implicit origin, or a Region start, also a duration with an implicit origin (in
that case the start of the Source). There is no good reason for using
a timecnt_t for this value, because the position component of a timecnt_t
(the origin for the duration) is implicit and always zero. So we make
this property into a timepos_t, and include a number of asserts() to check
for common possible coding errors related to the time domain
The length needs to use consistent time domains for duration and position,
and total_capture is a sample count. The "real" length of a whole
file region is the length of its source, so just defer to that.
Session::process_audition calls Graph::swap_process_chain()
to handle any pending graph changes (notably route removal
depends the graph to switch chains to drop references).
However this must not change the Graph::_trigger_queue
(which is refilled when processing resumes).
Previously routes were added to the trigger_queue, leading to
an inconsistent Graph state. When the terminal-count was reached
the trigger-queue was not empty. Process threads ran after processing
already completed and or concurrently with processing.
A common result of that was:
delayline.cc:70: virtual void ARDOUR::DelayLine::run(ARDOUR::BufferSet&, ARDOUR::samplepos_t, ARDOUR::samplepos_t, double, ARDOUR::pframes_t, bool): Assertion `lm.locked ()' failed.
This is required to be able to include
"audiographer/sndfile/sndfile_writer.h" in more than
one source file. which would otherwise lead to
duplicate symbol: AudioGrapher::SndfileHandle::..
In session file formats earlier than 7000, region position and length
are stored in distinct XML node properties. For 7000 or later, both
position and length are part of the "length" member. Fix reloading
this by noting session file format and loading position and length
more explicitly
Somewhat alarmed that gcc (at least) allows if (cue_recording ...) to be
used just like if (_cue_recording) even though the former is a class method
and the latter is a class member.
This causes issues if the header is included early on
in particular a conflict with gdkx.h
The reference to ‘Window’ is ambiguous `Gtk::Window` vs [X11]Window.
These are all defined via macros now. We send PropertyChange notifications when the value is set
even though it may not yet be in use.
This also changes the std::atomic used to protect the UIState<->Properties interlocking to
unsigned, to get defined behavior when the generation counter wraps
This doesn't yet correctly fix Pane::constrain_fract() constraints,
when moving the divider, but it does prevent child widgets from
being allocated with a size smaller than their minimum.
This fixes some layout and rendering issues (widgets that have
a too small allocation are not exposed and/or bleed into neighbors)
UIs only set a "shadow" value of most trigger properties, and use CAS to interlock (contention
is not expected to ever be an issue, it would imply two UIs being used to control this at
precisely the same time. The actual properties are updated whenever the trigger calls ::retrigger()