The track-header (gtk) is packed with 1px box spacing. This
is added at the top of each box (best seen by looking at the
group-tab vs track-header alignment in the editor).
However the actual track separator line on the canvas is at the
bottom of each track, aligning with the top of the next track
or automation-lane.
The first track however lacks a separator at the top, which
needs to be provided by the ruler. Once the canvas is scrolled
this ruler/canvas separator overlaps with the bottom separator of
each TAV.
Using ruler Rectangle::set_outline had various issues.
The outline extends outside the rectangle. It bled into the
video-timeline instead of the canvas' top y-axis pixel.
Also the separator was above the video-timeline, not above the
canvas. Hence a dedicated separator Line is preferable.
It also provides a consistent separator if no rulers are visible.
This fixes automation lanes bleeding into the ruler area.
The bounding box of all items in the main canvas group starts
at -0.5, and the cursor-scroll-group at -1.5. This is calculated
to include line-width, and outlines outside the item(s).
A scroll-group however must not extend its render area to
render those.
Before nutempo, ::find_next_region_boundary() used to return -1
when no boundary was found (now timepos_t::max is returned).
timepos_t::increment() returns the incremented value, not increments
the variable itself.
The region-gain envelop is an Automation list that uses AudioTime
regardless of the regions own position.
Since the actual audio data is using always using samples this
results in reliable envelopes without the reduced granularity of
BeatTime.
All points the list have to be in the AudioTime domain.
Previously it was possible to have a mixed-domain list e.g.
- add 2h:30min long source
- lock it to music-time
- set grid and snap to 1/8 note
- range select some range shortly after 2:25
- draw region-gain for range
<events>
a0 1
a492113664000 1.0000001192092896
a492113737500 0
a494032822500 0
a494032896000 1.0000003048365
b34560000 1.0000003048365
</events>
jack1 (which is Linux only) does not have a jack_client_stop_thread
API, and expects the application to call pthread_join().
This fixes an issue when the application is compiled using jack2 headers
but the application later runs using jack1's library.
When a session-range coincides with a loop-range location, moving
the session-range also updates the loop-range.
Keeping session and loop-range in sync can be useful if the whole
session is looped. However markers are treated individually, so
we need prevent invalid ranges.
If session-start and loop-start coincide, but loop-end is before the
end-marker, it is possible to move session-start beyond the loop-end.
Automation Controls (and controls in general) are now
only updated in realtime context. Either via automation-playback,
or via SessioEvent. This directly sets the Control:_user_value
(before emitting the Changed signal).
The GUI does not need to evaluate the control at a given point
in time, so the API call can be removed and unified.
This commit first removes all calls to "get_double" to ensure
that no special cases exist.
::automation_run() evaluates the value, possibly ahead of time
depending on latency-compensation. The actual value is set in
realtime-context via set_value_unchecked() -> actually_set_value()
which emits the Changed signal.
At this point in time Control::user_value is already set correctly.
There is no need to evaluate and interpolate again, at a potentially
incorrect (uncompensated) time: `_session.transport_sample()`.
This fixes an issue with the GUI Automation control showing an
outdated value when there is an "immediate jump" in the signal:
eg. add a latent plugin post-fader, then automate the Fader to jump
from 0dB to -inf dB (snap to grid) and play though that transition.
(Plugin controls were not affected by this bug, the process
cycle is split for those, but Mixbus internal AC were affected).
When a tempo map change originates from a drag, we know the required redraws have
already been done. Use a new bool member, ignore_map_change, to tell the Editor
to ignore the map change signal. For all other map changes, do the full reset.
We now simply move markers during drags, and do not seek to create/delete markers.
When the map is changed, we rebuild the markers from scratch. This might need optimization to avoid doing
when the editor itself changed the map.
When the loop-range is defined in BeatTime, the disk-reader encounters
rounding issues due to time-domain mismatches.
With a simple session fixed BPM at 120, 48kHz.
looping 1 bar exactly 2 sec at the start of the session:
```
Range::squish start: b0 end: b7680 squish: a113554560
Range::squish using modulo: b45 = a661500
Range::squish using modulo in TD: a5760
Range::squish using earlier(): a658560
```
The correct answer is a113554560 - 2 * 56448000 [SC/sec] = a658560
Calculating the modulo iteratively is not great, however usually
only one iteration is required.
Previously it was possible that the tempo-curve display was rendered
above a tempo-marker (e.g. create a marker in the between of existing
markers). With the tempo-curve in front, markers on the right
became inaccessible.
Code used to just push back new markers to the end of the relevant list, and
this would then the new marker to be deleted soon thereafter. Instead pass
an interator indicating where to place the marker in the list.
Note that we rely on the use of std::list<T> here to keep the iterator to the
existing marker valid.
PBD::Transmitter is neither thread-safe nor rt-safe. This likely
fixes a crash on macOS when process-threads are started.
Many threads simultaneously enter coreaudio_process_thread() and
log a message calling `PBD::info << .. << endmsg` simultaneously.