strictly speaking the include is not needed here since
g_atomic_compat.h includes glib.h. However it is idempotent,
the file does use glib methods, and g_atomic_compat.h may
one day be removed again.
Previously an empty RegionList was used (auto-partition
changes were never collected at rec-stop), furthermore
auto-partitioned regions do not have an old ARDOUR::AutomationList
(fade in/out) property (_have_old is false).
"While 'atomic' has a volatile qualifier, this is a historical
artifact and the pointer passed to it should not be volatile."
Furthermore "It is very important that all accesses to a
particular integer or pointer be performed using only this API"
(from https://developer.gnome.org/glib/2.68/glib-Atomic-Operations.html)
Hence initialization of atomic variables is changed to also use
this API, instead of directly initializing the value.
This also fixes a few cases where atomic variables were
accessed directly.
see also libs/pbd/pbd/g_atomic_compat.h
By supporting FMA extension, the number of instruction needed
for multiply accumulate to mix channels are reduced. Since,
this extension has been around since middle of 2012, more
computers have this instruction set available.
This uses an atomic counter and spins only on the writer side, which
preserves realtime behavior on the reader side. The spinning yields (by
using the same Boost function from Boost spinlocks) to be
scheduler-friendly.
Fixing this bug also lets us be able to confidently drop garbage early
in the writer if appropriate, so do that and avoid keeping dead wood if
possible.
This reverts commit f95439a502:
"add spinlock to RCU manager to protect concurrent reader() and update() calls"
This is useful in cases where an object owns child objects
which in turn hold a reference to the parent.
In this case PluginInsert has-a Plugin, which may have a reference
to the insert or the Route.
On GLIBC systems pbd_stack_size() adds __pthread_get_minstack,
this is no available on mac systems, causing issues with some
libraries used by plugins.
This is a glibc-only extension, so don't bother on other platforms.
Also, according to POSIX, PTHREAD_STACK_MIN is defined in limits.h, so
include climits just to be safe.
Some libraries use thread locals and hence increase the min
requirement.
This is seen on void-linux for example:
> linking a minimal program against cairo gives a
> __static_tls_size of 43008 bytes.
> Doing the same on Ubuntu focal and Debian bullseye,
> __static_tls_size is only 4608.
The distance is between a given offset in the buffer (probably a
read position at some point in time) and the write ptr. Any data after
the write ptr is "old" and not readable, and thus not worth overwriting
since we would not read it anyway.
This is needed primarily for a workaround for #7971. When importing a template
that has been exported on Ardour5 on MacOS we need to fix the paths of the
archive entries.
Later we can use this functionality also to handle imported templates if
templates with the same name already exist.
This commit only adds methods and members to FileArchive, it does not modify
anything to make regressions unlikely. This, however, leads to some duplicated
code. Eventually we should consolidate this a bit.
These changes compile okay for me (using VS2019) although they wouldn't link to my older-built libraries. Hopefully he'll be okay if he builds everything with the same compiler.
gcc, and recent clang-10 can construct new objects
using references as arguments.
However clang-8 (and MSVC?) do not:
"error: no matching function for call to 'operator new'"
The compiler apparently does not expand the template
class A <-> `A*` vs. `A const&`
for different cases.
This is a dumb stack allocator using LIFO allocation/free, with
a fallback to new/delete. This works well for small STL containers
in particular std::vector, but it's also suitable for std::map<>,
in particular copy constructing small POD maps (plugin pin mappings).
Eventually this could be combined with TLSF for a flexible
memory arena management. This is however not currently needed
for any the planned use-cases.
This code is ANSI C++98 compatible, and yet also works with
modern C++11, C++14
~StatefulDiffCommand() may trigger UndoTransaction::command_death()
which may delete the StatefulDiffCommand() that's just being destroyed.
This depends on the signal-connection order, which is undefined.
In any case when a shared_ptr<> object is being destroyed it means
that all references to it are already gone. There's no need to
emit drop_references from the d'tor.
This fixes a case when deleting a plugin, deletes all automation
undo/redo events:
<UndoTransaction name="add automation event">
<MementoCommand type-name="ARDOUR::AutomationList">
...
`delete this;` calls the d'tor which emits drop_references(),
that leads to UndoTransaction::command_death() destroying the
object, whichh causes a double free.
When a playlist is deleted and drops_references(), any
undo/redo StatefulDiffCommand referncing playlist invoke
Destructible::drop_references() of the Command.
This leads to command_death(). As opposed to UndoTransaction::clear()
the StatefulDiffCommand was not destroyed.
In case of playlists StatefulDiffCommand::_changes contains
PBD::SequenceProperty<std::list<boost::shared_ptr<Region> > >
and shared pointer reference of the playlist regions were kept
indefinitely.
This fixes the following scenario:
New session, import an file, delete the created track,
clean up unused sources (delete unused playlists)[, quit].
A reference to the imported region was kept, because of the
playlist's undo command (insert region). Yet the source file
was deleted.
PS. Most playlist changes are accompanied by GUI zoom/selection
MementoCommands. Those are currently never directly dropped.
command_death() leaves those in place.
This fixes an issue when copy/pasting plugins or aux-sends from
one track to another. After copying the processor, the state
is copied, however the Controllable state did save
the InlineControl flag, so this as lost.
(amend 93180ceea)
PBD::IgnorableControllable() is no longer used.
It also was problematic, because in every case where a
Controllable is required, min/max range and usually also
get/set value are significant.
the value is used by the parser context; the old code called it only after the *first* parser context
was created. therefore the first XMLTree::read() call has its behavior determined by libxml2's default
for this value, rather than by our explicit choice (do not treat whitespace as a note). All subequent
read() calls will use our value.
This variable inside libxml2 is actually per-thread, which just increases the stakes for calling
xmlKeepBlanksDefault() at the right time
This is similar to sort(1) --human-numeric-sort,
as opposed to naturally_less() negative numbers, hex-prefixes
and SI metric prefixes are taken into account.
This allows to indicate that a control should by default be displayed
inline in the mixer-strip.
Previously that was hard-coded for and enabled for send-level
controls only.
It's long been a guideline (and IIRC a Weff-c++ warning) that either all, or
none, of the copy methods should be defined, but this became a standard warning
in GCC9. Presumably to account for a later language change though I'm not sure
which.
I don't remember why the ChanMapping copy constructor can't just be a simple
copy (it's just a map of POD), but figure it's safer to just copy what that
does.
103ef2ba08 introduced an API to write raw data (const void*)
to a child process, along with the previous API to
write (std::string const&)
VideoMonitor uses write_to_stdin("fixed text"), and g++
interprets this to use the (const void*) API instead
of the std::string, which breaks communication.
It's a well established convention that pan y-axis automation,
or vertical uses (top) +1 for left.
This special cases rotary knobs (and horizontal sliders) to retain
a clockwise movement (or movement to the right) for panning to the
right.
There are still over a hundred left, but this addresses many already.
In particular @param references to undocumented parameters.
Most notably in audio_backend.h
This works around for compilers with non-static-data-member
initialization.
spinlock_t is-a struct { lockType _; } and BOOST_DETAIL_SPINLOCK_INIT
initializes the first member of the struct.
All defines of BOOST_DETAIL_SPINLOCK_INIT include c-style curly braces
to initialize the struct's data member.
However, modern C++ compiler interpret the braces differently resulting
in copy constriction of the initializer.
Depending on implementation, d8ae3fd may only construct the spinlock
once to `sl_init`. Later it is only copy-constructed and that leads to
compile and/or runtmime errors.
e.g. gcc-8.3 fails to compile
error: use of deleted function ‘boost::detail::spinlock::spinlock(const boost::detail::spinlock&)’