If _size_menu was non-null, we just return it. Ergo, it was already null when we reached
this line, which makes calling delete on it completely pointless
This test was added because of confusion about when/where dynamically constructed menus
were constructed and deleted. This should be consistent now, and this additional check
(on top of _size_menu itself being null) should be unnecessary
The manu is rebuilt every time it is required, no need to delete it. In addition, deleting it
in the middle of an event handler causes memory corruption because the entire menu (with all
items and submenus) is deleted before event handling for the menu is completed
All Immediate events have the same action samples, while other
parameters differ. Those events must not be removed by a
call to _remove_event(), particularly not SessionEvent::Overwrite
After an edit option the playlist is thawed and triggers
the butler thread (SessionEvent::Overwrite) to re-read the
playlist.
If another edit operation is started the butler may reads a
region using the region's new position, but the playlist's
old range.
See also 4db1c02bd1
Stop the engine if it was started for latency measurement
but measurement was aborted.
Previously the engine was kept running and the "Start' button
was not available.
If this happened during initial session loading, a user
would have to manually restart the engine to proceed.
When the screen-height is insufficient, the loudness-graph is
not included in the dialog. It is still visible in the image
saved with the export (save-export-analysis-image).
For tiny screens the conformity analysis may also be skipped.
The previous design had a race condition. When WaveViewThreads::stop_threads() was called, it would
first acquire the mutex, then set _quit, then call condition.broadcast(). But worker threads would
check _quit without holding the mutex. It was therefore for a thread to be delayed in its
own lock acquisition by the ::stop_threads() caller, then end up back in cond.wait() AFTER
the cond.broadcast() was done. Such a thread would sleep forever and never wake up.
This new design removes WaveViewDrawRequestQueue, which was a clean encapsulation of the
queueing aspects of WaveViewThreads, but unfortunately made correct mutex acquisition
and condition signalling/waiting needlessly complex. THe mutex, condition variable
and actual queue were moved into WaveViewThreads, and all worker threads execute a method
of the class which gives the appropriate code easy access to the mutex and condition var,
which must always be used together.
```
gtk2_ardour/ardour_ui.cc:2060: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
/usr/include/architecture/i386/math.h:343: note: candidate 1: double pow(double, double)
/usr/include/c++/4.2.1/cmath:357: note: candidate 2: float std::pow(float, float)
```
This replaces a Mutex and adds additional read-locks.
This is needed to address some threading issues with rt-threads
calling auto_loop_location() while the GUI changes locations.
Since locations are C-pointers this is still not entirely safe!
Locations::remove() may delete a location while a pointer
to it is being used in another thread.
Previously the freewheel export thread directly called
Session::butler_transport_work(). The butler thread
may concurrently call the same function. This can lead
double free or memory corruption (see below)
Now export thread summons the butler and does nothing
until it completed its work.
```
Export Thread:
3 XMLNode::~XMLNode
4 ARDOUR::AutomationList::snapshot_history
5 ARDOUR::AutomationList::start_write_pass
6 ARDOUR::Automatable::non_realtime_locate
7 ARDOUR::Route::non_realtime_locate
8 ARDOUR::Session::non_realtime_locate
9 ARDOUR::Session::butler_transport_work
10 ARDOUR::Session::process_export_fw
Butler thread:
7 XMLNode::~XMLNode
8 ARDOUR::AutomationList::snapshot_history
9 ARDOUR::AutomationList::start_write_pass
10 ARDOUR::Automatable::non_realtime_locate
11 ARDOUR::Route::non_realtime_locate
12 ARDOUR::Session::non_realtime_locate
13 ARDOUR::Session::butler_transport_work
14 ARDOUR::Butler::thread_work
15 ARDOUR::Butler::_thread_work
```
Previously x-axis threshold was in samples. This is
useless unless zoomed in to the max. So in most cases
the first-move was always in x-direction, making constrained
y-axis drags near impossible.
Furthermore the threshold for copy-drags was increased
as per #8686