Querying available buffersizes and sample-rates requires access
to the device. Almost all ALSA devices are limited to
a single user-space application so we unconditionally try
to request access to the device.
Even though SIGINT is intended to be sent from terminals only,
it is more successful at terminating various child processes than
closing stdin and sending SIGTERM.
This effectively triggers a Session::request_overwrite_buffer
via Playlist::notify_contents_changed when the time-domain of a
Region changes.
When the time domain of a MIDI region changes, Region boundaries
and events positions change ever so slightly. The playlist has
to be rendered again to take this into account.
When MIDI regions with different time-domains are layered, notes
may not be resolved in correct order. Previously changing time-domains
to address this did not result in the playlist being reread.
This adds a special case of "flush/resolve" to restore the
state of an upper layer opaque MIDI region while at the same time
resolving notes of a lower layer region.
This honors transparent/opaque property of MIDI regions.
Previously all MIDI regions played as if they were unconditionally
transparent.
Further work is needed for backwards compatibility (and default
setting).
The iterator into the model can become incorrect in the sense that it is no longer the correct
next event to play. This can happen at least with a tempo map change, and possible under other
conditions. Catch this when it happens, and act as if we reached the end of the trigger
Some music using square waves can inadvertently be interpreted as valid
LTC frame. However the encoded data is not a valid timecode, which can
lead huge A/V offsets, or other issues.
These also had the wrong case: case is relevant here, classes are uppercase,
other things (properties and instances) are lowercase. However, they seem to
be entirely unused now, so simply remove them instead of fixing this.
This makes "sequential" more or less mean an octave vertical interval,
but only for in-key mode. For chromatic mode, "sequential" is still just a
naive wrap-around layout for every note.
This juggles the implementation slightly in a way that's more resilient to
mistakes: the representation of pads in the surfaces is always fully reset
before setting up the grid, and a state message is sent for every single pad
once after the scale algorithm sets things up.
This means that scale algorithms don't need to deal with hairy edge cases like
running off the end of the scale or the valid range of MIDI notes.
"Mostly" because there are still some issues with horizontal overlap between
entries, but I think that's something that needs to be addressed separately.
Like earlier issues, this was caused by using a screen-derived or default
cairo/pango context. I also tinkered with some constants to make things look
sensible to me, and hopefully everywhere since it should always look the same
with the context fix.
We no longer have a distinct "position" property, because the "length" property
defines both extent and position. But we must not call ::recompute_at_start()
when the position has not changed, so here we use Region::last_length() to
simulate the position property.
Tests would fail as:
Test name: AutomationListPropertyTest::basicTest
equality assertion failed
- Expected: 4
- Actual : 5
It is slightly more informative when the size assertion is the last
check and it fails as:
- Expected: state
- Actual : time-domain
The performance benefits from checking size first is not relevant.
With this, all tests are passing for me.
While Ardour doesn't use TDD and has low test coverage, it is nice to
maintain that all active tests are passing.
Original code is of questionable historical provenance, and
was needlessly (it seems) complexity. New code is relatively
simple arithmetic linear interpolation.
Session dirs must exist when loading Sources of a project.
SourceFactory::init() starts the PeakFileBuilder background thread
early on when libardour is initialized.
This thread [re-]creates missing peak files when Sources are
created or loaded. However AudioSource::prepare_for_peakfile_writes
assumes the peak/ folder exists. This may not be true, which lead to
"AudioSource: cannot open _peakpath [..] (No such file or directory)"
errors.
Also drop creation from Source::get_transients_path() as this
may be called concurrently from Analyser background threads.
This reverts commit 96ebac646d.
There are some valid cases where refill is called from the GUI
thread. e.g adding tracks, or adding channels to an existing track.
This happened initially during session load.
The GUI thread performed a direct refill (blocking wait)
`Session::post_engine_init() -> Track::seek() -> DiskReader::seek() -> DiskReader::do_refill_with_alloc()`
while concurrently the butler thread does the same:
```
Session::butler_transport_work() -> Track::non_realtime_locate() -> Route::non_realtime_locate()
-> DiskIOProcessor::non_realtime_locate() -> DiskReader::seek() -> DiskReader::do_refill_with_alloc()
-> DiskReader::refill_audio()
```
We do not want the GUI to wait, so now we just request a locate
and let refill happen in the background.
Add a list of marker locations to the session, for the the UI to add the
current location to when "add-region-cue-marker" happens whilst recording.
On record-stop, create source markers at the locations in that list in all
newly-recorded audio regions.
This change still runs the triggerbox during latency-preroll, but as with the disk reader,
the transport speed argument is set to zero. The triggerbox notices this and behaves
appropriately (I think !)
When an archive are saved, a new folder in interchange/ is created,
named after the archive. However session-archive also retains files
in the session-folder that Ardour does not know about.
This can cause that the the original interchange folder is retained.
It will be empty with just the .DS_Store file in it. The result is
that the session may not load if there is an ambiguity.
Triggerboxen were being executed during the latency preroll phase, which is
inappropriate. ::fast_forward() will prepare them to run at precisely the
correct time. So we add an explicit clause to avoid this.
Found via `codespell -q 3 -S *.po,./.git,./share/patchfiles,./libs,./msvc_extra_headers,./share/web_surfaces,*.patch -L ba,buss,busses,discreet,doubleclick,hsi,ontop,ro,scrollin,seh,siz,sord,sur,te,trough,ue`
Rather than start at zero, we now search backwards for the first relevant cue
before the locate position, making our task in ffwd'ing from there much simpler
since there are no other cues to consider
Also remove Meter:: versions of related methods, because they are not necessary. We
only need metrical information for operations like ::round_to_bar()
* there are rare cases where a midi clip would not advance the ffwd position, looping endlessly
* this problem did not occur when the user chose an explicit Follow Length (different code path)
This workaround bypasses RegionMap and SessionPlaylist APIs
(region_use_count, destroy_region) which are not directly
applicable to Triggerboxes. There are likely various edge
cases until TriggerBoxes integrate with Session Playlist.
e.g. whole file regions generated for regions/source used by
triggerboxes are cleaned up.
A compound region itself may be unused, but the nested source
it provides can be used in another region compound.
In this case the first, unused, region needs to be saved
to save the nested source.
Constructing a playlist from another playlist plus an offset used the wrong
RegionFactory::create method. By failing to pass in the offset to the region
constructor, the newly created region gets its envelope (and possibly other
automation data) from the start of the existing region, not its own start.
There was a logic error previously which failed to consider follow actions (and follow count).
Now we find a relevant cue, and use follow actions and follow counts as we move forward
in time
This fixes an issue with LV2 plugin that unconditionally
initialize LV2 Atom ports even if they are not connected.
eg. JUCE7 produces LV2s at the time of writing.
The actual goal here is to use direct InterpolationStyle serialization
in MidiSource (identical to AutomationList). enum_2_string()
does not work for Evoral types.
As side-effect virtual base-classes have been changed to pass
Parameters as const references
This fixes an issue when creating tracks or busses with a colon
in the name. Renaming those tracks later IO::set_name()
crashed in current_name.replace(std::string::npos,..).
`IO::build_legal_port_name` uses ";" instead of ":" while
`IO::set_name` replaced it with a "-".
Initially the IO name included the colon, so ports created
use a semicolon. But after renaming the IO, ::set_name() applies
the replacement and the IO's name is changed to include the "-".
This leads to a conflict with ports that already have the semicolon
in the port-name.
Loop Location start="a1665678660" end="b145920"
Loop-end (at 122BPM) is a2109859636
at 48kHz this is sample 1794098.32
Now play the loop and play sample 1794098 = a2109859248
Range::squish start: a1665678660 end: a2109859636 squish: a2109859248
squish() does nothing, since there are still 388 superclock-ticks
until the end of the loop.
However, DiskReader::get_midi_playback convertes the value back
to samples(), this leads to effective_start == loop_end;
resulting in an endless loop.
Thanks to MikeLupe to provide a session to reproduce this issue.
So far group-override "inverts" group behavior. Disabled groups
(or group settings) are enabled and vice-versa.
When the setting is disabled, groups can only ever be disabled
(Controllable::NoGroup) and group-override will not enable them
(Controllable::InverseGroup).