Ardour uses some global variables and singletons. These global variables
can be initialized with a value prior to program execution (especially
if they are const), but some of the static variables are modified, and
it is crucial that they always are reset when switching to another
session. To keep things simple and explicit and consistent, we thus
introduce Temporal::reset() to reset TempoMap (and later on also the
superclock rate). This is somewhat similar to Temporal::init(), which
usually only is invoked once (on program start) to initialize singletons
(such as the TempoMap).
9964f20c added TempoMap initialization to Session::create() ... but only
when not using a template. This create method is mainly preparing the
filesystem for a new session, and TempoMap initialization doesn't seem
like a perfect fit for it. It also seemed odd that it only initialized
TempoMap for clean new sessions, while existing sessions and templates
initialized it elsewhere.
Instead, invoke the TempoMap initialization early in the Session
creation process. This might introduce an extra and unnecessary TempoMap
initialization when loading an existing session or using a template, but
that will be cheap and do no harm, while providing a guarantee that we
always use the same default value.
Directly loading a new session (Session > Recent) stops the engine
when the sample-rate mismatches. All is fine.
When closing a session (Session > Close), the engine is kept running.
Loading a different session with different sample-rate shows
the "SR mismatch" dialog. Reconfiguring the engine then does not call
`Session::immediately_post_engine` again.
* Use an atomic reference count since the freeze-thread
can call use_playlist.
* Remove explicit argument to construct unused playlist
because playlists are unused by default. This also
lead to use-count becoming negative (or rather UINT32_MAX)
This is mostly a simple lexical search+replace but the absence of operator< for
std::weak_ptr<T> leads to some complications, particularly with Evoral::Sequence
and ExportPortChannel.
After recovering from a crash, the user still needs to
retain the option to ignore the changes that were done
just before the crash after investigating them (or save them
into a snapshot).
Previously crash recovery unconditionally overwrote the
session file (see discussion on bug tracker).
This was removed in
bf0a5256472316df357b
"SaveState" was chosen because "State" prefix overlaps with
"Stateful", and "SessionState" overlaps with "SessionEvent"
debug names. `-DState` or `-DSession` overlap respectively
with unrelated debug output.
Archiving creates a dedicated mono file for each Source.
When the original session has (embedded) stereo files, the
channel needs to be temporarily set to 0.
This happened initially during session load.
The GUI thread performed a direct refill (blocking wait)
`Session::post_engine_init() -> Track::seek() -> DiskReader::seek() -> DiskReader::do_refill_with_alloc()`
while concurrently the butler thread does the same:
```
Session::butler_transport_work() -> Track::non_realtime_locate() -> Route::non_realtime_locate()
-> DiskIOProcessor::non_realtime_locate() -> DiskReader::seek() -> DiskReader::do_refill_with_alloc()
-> DiskReader::refill_audio()
```
We do not want the GUI to wait, so now we just request a locate
and let refill happen in the background.
When an archive are saved, a new folder in interchange/ is created,
named after the archive. However session-archive also retains files
in the session-folder that Ardour does not know about.
This can cause that the the original interchange folder is retained.
It will be empty with just the .DS_Store file in it. The result is
that the session may not load if there is an ambiguity.
This workaround bypasses RegionMap and SessionPlaylist APIs
(region_use_count, destroy_region) which are not directly
applicable to Triggerboxes. There are likely various edge
cases until TriggerBoxes integrate with Session Playlist.
e.g. whole file regions generated for regions/source used by
triggerboxes are cleaned up.