This will eventually have to be fixed, currently split-channel
files are not correctly tagged and post process commands
are only emitted for the last file.
But fixing this is complicated, so meanwhile a workaround is used.
Eventually this commit should be [mostly] reverted!
When a track's output is not connected, we assume
its output playback latency matches that of the master-bus.
This is to prevent the track's output latency to float
freely (see also a556e96ed0).
This failed if a track is connected to another track which is
not connected.
On Intel systems ArdourCanvas::COORD_MAX (1.7e+307) was rounded
to (gint) -2147483648. gtk+ treats negative window size-requests
as 1px.
However on ARM, COORD_MAX was truncated to +2147483648, gtk+ limits
this to 65535. Most WM/Xwin systems cannot handle windows this large.
It also exceeds the max size of cairo [image] surfaces.
This issue was introduced in a1c67b4ad7
when "natural_size" was removed. Before that change infinitely large
canvas had a natural_size of 2x2 px.
Previously every region fragment was added one at a time,
with each emitting signals and updating the GUI. If there are a
few thousand regions Ardour can freeze for a significant amount
of time.
There is still the issue that the GUI freezes after the progress-bar
reached the end: consolidate overlapping ranges after analysis, then
add regions.
And Playlist::flush_notifications still emits
RegionFactory::CheckNewRegion() for every region individually
and RegionListBase::add_region becomes the bottleneck.
But at least adding 7k regions now returns in under 5 minutes
instead of taking over an hour.
This fixes an issue with the videotimeline not being shown
when reloading a session. Editor::set_state() restores the grid,
which in turn changes ruler visibility. This triggers
store_ruler_visibility() and the saved session state was lost.
This fixes an issue when loading sessions in "safe mode".
Internal side-chain sends are removed if the target port
does not exist. Also other port connections are lost if the
target port does not exist.
Since cc6c0f1263 there is no Properties::position event
when a region is moved. So notify_region_moved() or
notify_region_start_trimmed() was never emitted and
Session::maybe_update_session_range() was not called.
When a track's output is not connected, but the track feeds
other tracks via sends (common case in Mixbus) the stem
export of the track was not correctly aligned.
The track is correctly latency compensated (due to sends), but
the unconnected port's latency is not set.
However stem-export uses the private latency of the port as alignment.
* audio files can be named "0bpm" to make them un-stretchable
* however they still need a sensible beatcnt, and therefore tempo
* assume tempo 120bpm and assign a beatcnt based on the file's length
* the user might later enable stretch, and we need to be sensible about it
VCAManager::create_vca sets PI::order while holding the
VCAManager:lock mutex. PI order changes emit a "changed" signal
which in turn can result in querying a list of all strips
(reassign_track_numbers) which requires the VCA mutex:
See also 729ff35faf
```
#2 Glib::Threads::Mutex::Lock::Lock(Glib::Threads::Mutex&) (this=0x7fffffffb070, mutex=...) at /usr/include/glibmm-2.4/glibmm/threads.h:687
#3 ARDOUR::VCAManager::vcas[abi:cxx11]() const (this=0x5555599b6d10) at ../libs/ardour/vca_manager.cc:77
#4 ARDOUR::Session::get_stripables(std::__cxx11::list<boost::shared_ptr<ARDOUR::Stripable>, std::allocator<boost::shared_ptr<ARDOUR::Stripable> > >&, ARDOUR::PresentationInfo::Flag) const (this=0x55555bf03910, sl=std::__cxx11::list = {...}, fl=127) at ../libs/ardour/session.cc:3949
#5 ARDOUR::Session::ensure_stripable_sort_order() (this=0x55555bf03910) at ../libs/ardour/session.cc:2634
#6 ARDOUR::Session::notify_presentation_info_change(PBD::PropertyChange const&) (this=0x55555bf03910, what_changed=...) at ../libs/ardour/session.cc:7016
[ .. connect same thread ..]
#13 ARDOUR::PresentationInfo::send_static_change(PBD::PropertyChange const&) (what_changed=...) at ../libs/ardour/presentation_info.cc:113
#14 ARDOUR::PresentationInfo::set_order(unsigned int) (this=0x5555619ceca0, order=5) at ../libs/ardour/presentation_info.cc:288
#15 ARDOUR::Stripable::set_presentation_order(unsigned int) (this=0x5555619ce8a0, order=5) at ../libs/ardour/stripable.cc:55
#16 ARDOUR::VCAManager::create_vca(unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
(this=0x5555599b6d10, howmany=1, name_template="VCA %n") at ../libs/ardour/vca_manager.cc:105
```
Control surfaces c'tor usually subscribe to signals e.g.
PortConnectedOrDisconnected. This happens after the parent BaseUI
is created, but before set_active() -> BaseUI::run() is called.
At this point in time there is no run_loop thread.
There are two options to handle AbstractUI::call_slot():
A. Queue the event in the event-loop, using the thread-local
request buffer of the caller. Then hope the BaseUI
thread is started, and calls ::handle_ui_requests() before
the memory pool runs out of space.
B. Handle the event in the calling thread. -- This may not be
rt-safe and may call functions with locks held by the caller.
It will however not accumulate events.
This takes approach (B). If _run_loop_thread is NULL, directly
handle the signal.
In the past, prior to 50abcc74b5, approach (A) was taken.
NULL never matched Glib::Threads::Thread::self().
This also reverts a prior attempt (e417495505) to address this issue.
Changing banks refills the dropdown. This cannot be avoided
since unnamed banks are not in the dropdown, and the dropdown
content can change dynamically. Scroll-wheel does not work reliably.
The Model must be destroyed after the iterator, otherwise
the iterator's d'tor will cause memory corruption trying to lock
the model:
```
Invalid read of size 4
at pthread_rwlock_unlock (pthread_rwlock_unlock.c:39)
by Glib::Threads::RWLock::ReaderLock::~ReaderLock() (threads.h:828)
by void boost::checked_delete<Glib::Threads::RWLock::ReaderLock>(Glib::Threads::RWLock::ReaderLock*) (checked_delete.hpp:36)
by boost::detail::sp_counted_impl_p<Glib::Threads::RWLock::ReaderLock>::dispose() (sp_counted_impl.hpp:89)
by boost::detail::sp_counted_base::release() (sp_counted_base_gcc_atomic.hpp:120)
by boost::detail::shared_count::~shared_count() (shared_count.hpp:432)
by boost::shared_ptr<Glib::Threads::RWLock::ReaderLock>::~shared_ptr() (shared_ptr.hpp:335)
by Evoral::Sequence<Temporal::Beats>::const_iterator::~const_iterator() (Sequence.h:224)
by ARDOUR::MIDITrigger::~MIDITrigger() (triggerbox.cc:2037)
by ARDOUR::MIDITrigger::~MIDITrigger() (triggerbox.cc:2039)
by ARDOUR::TriggerBoxThread::delete_trigger(ARDOUR::Trigger*) (triggerbox.cc:4386)
by ARDOUR::TriggerBoxThread::thread_work() (triggerbox.cc:4314)
by ARDOUR::TriggerBoxThread::_thread_work(void*) (triggerbox.cc:4285)
by fake_thread_start(void*) (pthread_utils.cc:101)
by start_thread (pthread_create.c:477)
by clone (clone.S:95)
Address 0x28229798 is 24 bytes inside a block of size 56 free'd
at free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
by Glib::Threads::RWLock::~RWLock() (in /usr/lib/x86_64-linux-gnu/libglibmm-2.4.so.1.3.0)
by Evoral::Sequence<Temporal::Beats>::~Sequence() (Sequence.h:68)
by ARDOUR::AutomatableSequence<Temporal::Beats>::~AutomatableSequence() (automatable_sequence.h:31)
by ARDOUR::MidiModel::~MidiModel() (midi_model.h:58)
by ARDOUR::MidiModel::~MidiModel() (midi_model.h:58)
by void boost::checked_delete<ARDOUR::MidiModel>(ARDOUR::MidiModel*) (checked_delete.hpp:36)
by boost::detail::sp_counted_impl_p<ARDOUR::MidiModel>::dispose() (sp_counted_impl.hpp:89)
by boost::detail::sp_counted_base::release() (sp_counted_base_gcc_atomic.hpp:120)
by boost::detail::shared_count::~shared_count() (shared_count.hpp:432)
by boost::shared_ptr<ARDOUR::MidiModel>::~shared_ptr() (shared_ptr.hpp:335)
by ARDOUR::MIDITrigger::~MIDITrigger() (triggerbox.cc:2037)
by ARDOUR::MIDITrigger::~MIDITrigger() (triggerbox.cc:2039)
by ARDOUR::TriggerBoxThread::delete_trigger(ARDOUR::Trigger*) (triggerbox.cc:4386)
by ARDOUR::TriggerBoxThread::thread_work() (triggerbox.cc:4314)
by ARDOUR::TriggerBoxThread::_thread_work(void*) (triggerbox.cc:4285)
by fake_thread_start(void*) (pthread_utils.cc:101)
by start_thread (pthread_create.c:477)
by clone (clone.S:95)
```
* intercept {pgm|bank}-change messages, and replace them with triggerbox values
* check is_set() extensively; we have arrays of pgms but most are unused
* initialize patches to GM standard (drums on 10) in case file has none
* in the case where file had none, check the Auditioner to see if user set any
* in the case where a file has patches, use those instead
* also stash the UsedChannels so we can show only the used chans in the UI
* if a file has program-changes, then it will set() my patches
* if a file does *not* have PCs, the user might choose one (which sets() it)
* if the next file does *not* have PCs, we should preserve the user's selection
* if the next file has PCs, it will set() it (losing the user selection)