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
This fixes another deadlock calling send_change with the
Playlist's RegionWriteLock held.
In this case due to "MIDI region copies are independent"
when duplicating MIDI regions.
```
ARDOUR::Region::send_change ()
PBD::Stateful::apply_changes ()
ARDOUR::RegionFactory::create ()
ARDOUR::RegionFactory::create ()
ARDOUR::MidiRegion::clone ()
ARDOUR::RegionFactory::create ()
ARDOUR::Playlist::duplicate ()
```
This fixes various issues with signal emission(s) when creating
regions from withing playlist operations.
eg. Playlist::duplicate() takes RegionWriteLock() and then calls
RegionFactory::create().
see also 6a82aa392c
RegionInsertDrag or Consolidate Range or any other operation
calling Playlist::add_region() previously triggered RangesMoved()
which resulted in DiskReader::move_processor_automation()
NB. insert + ripple still moves automation correctly.
TmpFileRt::get_samples_written() returns the number of
samples written *to disk*. It is only valid after the FileFlushed
signal is emitted.
This fixes an assert() with Limiter and Analyzer being configured
with a too low total sample-count, leading to an overflow in
the analysis graph array.
1) if there is no current dialog, allow some other window to handle the keyboard event
2) make the binding (which is hard coded) visible as static members of Keyboard
In some cases old and/or conflicting port names were saved
with the session (e.g. "Faderport" for FP1,8). Loading old sessions
then merges this state into the config, which could lead to
port-registration failure when the surfaces was enabled.
Follow Session::setup_bundles() lead for single channel
MIDI bundles. This cleans-up the port-matrix display and
removes redundant names. The underlying engine port-name
is not of interest to the user.
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.