Rely on previously collected I/O port-list, skip expensive call
to get_physical_inputs() and rely on RCU port list alone.
Also skip port_is_mine() test in optimized builds.
* You can now show a selector for each track, rather than one global dialog
* Removed the 'cancel' button: it was too easy to unintentionally revert your selection
* Correctly sort and name new playlists when they are added or renamed from the P menu
* Fix problem where list contents disappeared when changing desktops (on_unmap_event)
* avoid memory allocation (remove std:set<>&)
* skip nested loop using port-names as IDs
However this adds a bit of extra cost in case input ports are
monitored: get_port_by_name() and get_buffer()
glib atomic operations include a complete act as a full
compiler and (where appropriate) hardware memory barrier.
std::atomic<> allows dedicated acquire and release barrier
semantics which are not available with glib.
* Add an option to use a playlist without stealing its ownership. (libardour)
* Tracks emit PlaylistAdded when a new playlist is created either by copying or by creating a new empty pl
* no version-check should be necessary because when opening an old session,
playlists can be looked-up by discrete names and will be tracked by ID thereafter
Prior implementation:
Bouncing a range and naming it "chorus" resulted in:
..a region per track, and they were all named "chorus"
...a file per track, with the name "chorus-{playlist name}"
New implementation:
Bouncing a range and naming it "chorus" results in:
..a region per track, with the name "chorus-{playlist name}"
...a file with the same name as the region
This fixes cases where a widget's parent isn't the
top-level window and additional offset has to be taken
into account.
So far this has not been an issue since this method was only
used for floating text entries.
While POSIX defines a single contiguous range of numbers that
determine a thread's priority. Win32 defines priority classes
and priority levels relative to these classes.
pthread maps those to -15 .. +15 with the top six ones
corresponding to REALTIME_PRIORITY_CLASS and max being
THREAD_PRIORITY_TIME_CRITICAL
Note that the PA backend can USE_MMCSS_THREAD_PRIORITIES
and PBD::MMCSS::set_thread_characteristics() directly for
the I/O threads.
RegionFactory::CheckNewRegion signal is emitted directly
after region-creation from RegionFactory::create().
At this point in time the region is not on any playlist.
This if fine for EditorSources, but the new RegionList design
only shows regions that are on the timeline.
CheckNewRegion() -> EditorRegions::add_region()
-> EditorRegions::regions_changed() ignores regions w/o playlist.
Later Playlist::add_region_internal() sets the playlist but
calls Region::clear_changes() to not send all individual changes.
So Region::RegionsPropertyChanged is not emitted either.
We need to notify the EditorRegions *after* setting the playlist.
The downside of this is that more signals than necessary are
emitted.
If the wrong device profile is selected (ex Xtouch One) but another device
is connected (Xtouch), it is possible to have a master fader on the
device, but not in the code. This would then cause a crash when the
master fader was touched.
This just protects from a wrong configuration.
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
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.
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
```
It is not needed in the relative case and causes issues when taking
sessions between platforms.
On windows, the default path would be "\export". When that is used
on linux the resulting fullpath would end up as
/your/session/path/\export
which is then not found on the file system.
This change is consistent with how relative paths are normally written and
does cure the default path when moved across platforms.
It does not solve the larger issue of mixed directory separators.
A relative path of "export\myMixV1" will still fail when moving between
platforms.
Previously the following were treated as equal
"MIDI_foo" == "MIDI bar"
So std::map<> PortManager::_ports and PortEngineSharedImpl:_ports
could only have either. This resulted in missing ports
and missing calls to existing ports in cycle_start().
This mainly affected MIDI tracks with imported files, since there
is "MIDI Clock in", and imported files result in tracks
"MIDI_file-name".
This issue was introduced in 6.6-200-g60ff3ef764
We do need to know that a reversal is intended before we do a locate, but we should
not enter Reversing before the declick is finished. So instead, we add a new
member, _reverse_after_declick to keep track, and enter Reversing just before
we start the locate
select(2) can only handle file descriptors up to 1024, and there are fairly easy to reproduce
cases where the file descriptor used here is larger than that.
Portmanager uses "ports" as local variable in various places
(usually vector<string>). While the compiler is fine with that,
it is confusing when debugging or reading code.
Since Ardour 6, a transport speed of 200% will also double
DSP load. Under the hood Ardour rolls twice the distance and
the output is downsampled.
Vari-speed > +/-200% will likely cause dropouts with many
sessions on most systems, users should explicitly select it.
The TransportFSM is now responsible for deciding what to do at all transport state transitions. The Session (via the TransportAPI) merely
provides mechanism (locate, start, stop, set_speed). Default and most recent speed requests are managed by the TransportFSM too