When we create a new session and are using a template from an old version of
Ardour, we should not issue the VersionMismatch dialog and not make a copy of
the session file for the old version.
We need to extend the signature of Session::load_state() to tell it if we are
creating a session from a template. Session::_is_new cannot be used for it
because it has a the semantics if to auto connect the the master bus.
Note that this is done at the GUI level, might need to double check if there are
other paths into a "save" that should be covered. Control surfaces use the action, but
Lua comes to mind
Direct call to Session::cleanup_sources() from ARDOUR_UI::cleanup()
didn't zero initialize size. This centralizes initialization,
so cleanup_trash_sources() does not need to explicitly clear it.
Previously when loading Ardour v2, v3-5 sessions, tracks were
created with a dummy name "toBeResetFroXML".
In v6, Track::init() creates a playlist when the track name is
not empty. Later Track::set_state() calls set_name(). When a
playlist exists, the playlist's name is set to match the track's name.
When loading v6 sessions none of this happens. A previously loaded
playlist will be assigned by ID.
Older versions identified Playlists by name and by the time the
playlist is assigned, there may be ambiguities. With the default
(track-name = playlist-name) two playlists with the same name exist:
(1) the playlist loaded from the session file
(2) the playlist created by Track::init()
Playlists are stored in an ordered std::set<shared_ptr<Playlist>>,
and name-lookup iterates over the set.
When loading an old session after starting Ardour, it is very
likely to always lookup the playlist (1), because new, later
allocations from (2) are on top of the heap and ordered last.
The session seemingly loads correctly, except for lingering,
unused empty playlists "toBeResetFroXML" renamed to "Track name"
that were never deleted.
However when loading an old session from a running instance,
ordering is mostly random, and many tracks end up with using
the empty playlist (2) instead of the correct playlist (1).
Otherwise this will lead to a corrupt state:
ERROR: Session: XMLNode describing a AudioRegion references an unknown source id
ERROR: Session: cannot create Region from XML description. Can not load state for region
ERROR: Playlist: cannot create region from XML
and a track without playlist is created, resulting in a later crash.
Eventually SessionPlaylists::load() needs to handle this gracefully,
but this should help catch cases causing the actual issue.
Various operations clear the history (e.g. cleanup). In that
case the GUI correctly had an empty Undo/Redo history, but the
file on disk was left in place.
Next session load restored the old, incorrect Undo/Redo history.
ARDOUR::Session::remove_routes() explicitly calls
save_state (_current_snapshot_name)
Update assert() to treat an empty name
equivalently as explicitly specified _current_snapshot_name
undo may restore locations, which may trigger a state-save.
This can result in a deadlock:
Location::set_state () -> Locations::get_state()
both acquire a the same lock:
#2 0x000055a8421836d0 in Glib::Threads::Mutex::Lock::Lock(Glib::Threads::Mutex&) (this=0x7ffe38dcad40, mutex=...) at /usr/include/glibmm-2.4/glibmm/threads.h:687
#3 0x00007fc637731e9c in ARDOUR::Locations::get_state() (this=0x55a8466d4740) at ../libs/ardour/location.cc:1075
#4 0x00007fc637bf14b7 in ARDOUR::Session::state(bool, ARDOUR::Session::snapshot_t, bool)
(this=0x55a846d0f050, save_template=false, snapshot_type=ARDOUR::Session::NormalSave, only_used_assets=false) at ../libs/ardour/session_state.cc:1406
#5 0x00007fc637bed2c8 in ARDOUR::Session::save_state(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool, bool, bool)
(this=0x55a846d0f050, snapshot_name="", pending=true, switch_to_snapshot=false, template_only=false, for_archive=false, only_used_assets=false) at ../libs/ardour/session_state.cc:815
#6 0x00007fc637b4d967 in ARDOUR::Session::auto_punch_start_changed(ARDOUR::Location*) (this=0x55a846d0f050, location=0x55a848fe11d0) at ../libs/ardour/session.cc:1395
#7 0x00007fc637b4da21 in ARDOUR::Session::auto_punch_end_changed(ARDOUR::Location*)
(this=0x7fc637b4da21 <ARDOUR::Session::auto_punch_end_changed(ARDOUR::Location*)+67>, location=0x7ffe38dcbf10) at ../libs/ardour/session.cc:1403
[..]
#14 0x00007fc637730a2a in ARDOUR::Location::set_state(XMLNode const&, int) (this=0x55a848fe11d0, node=..., version=6000) at ../libs/ardour/location.cc:715
#15 0x00007fc637732428 in ARDOUR::Locations::set_state(XMLNode const&, int) (this=0x55a8466d4740, node=..., version=6000) at ../libs/ardour/location.cc:1130
#16 0x000055a842388dd7 in MementoCommand<ARDOUR::Locations>::undo() (this=0x55a84d1e5f10) at ../libs/pbd/pbd/memento_command.h:141
#17 0x00007fc635b50707 in UndoTransaction::undo() (this=0x55a84d513b80) at ../libs/pbd/undo.cc:128
#18 0x00007fc635b50e1c in UndoHistory::undo(unsigned int) (this=0x55a846d11338, n=0) at ../libs/pbd/undo.cc:267
#19 0x00007fc637c0dfff in ARDOUR::Session::undo(unsigned int) (this=0x55a846d0f050, n=1) at ../libs/ardour/session_state.cc:5577
This is in preparation for saving state while the session is
record-arm'ed. Most notably config changes and undo/redo.
In case both normal and pending save happens, pending must be
last and is required to recover from crashes during recording.
* update AFL position when preference changes
* "after post-fader processors (before pan)" is before
the main-out (not at the end).
* Fix "immediately post-fader":
The amp, when added was the last element. ++after_end then
made the iterator point to .end()
This likely worked in the past when the monitor send was added
immediately after adding the fader/amp before any other processors.
Remove need for explicit `initialize_latencies` call that used
to be called from GUI-thread post_engine_init(), as well as
Session::engine_running().
Further reduce calls, `graph_reordered` implies a latency-update
and fix ordering issue. update_latency_compensation() must be called
*after* resort_routes().
gcc can recognize various regexps in comments. Since C++17 provides
[[fallthrough]], using /* fallthrough */ consistently seems
appropriate until we switch to C++17.
see also https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Parsing MIDNAM is what takes the most time.
"Reset Remote Controls" message is misleading (it means MMC), not
control-surfaces, which a user may have none.
Session::Controllables is a shared_ptr<> list. As long
as the session exists the Controllables will be around. Destroyed(*)
can only be called after the session is destroyed and releases the
shared_ptr<>
NB. this code had a nice hack to construct a "shared_from_this"
workaround. For future reference:
struct null_deleter { void operator()(void const *) const {} };
boost::shared_ptr<Controllable>(c, null_deleter())
This addresses issues with session-cleanup and region-cleanup in
some sessions.
The root-cause why some unused playlists were saved in the session XML
under <Playlists> and not <UnusedPlaylists> is not known.
Early 6.0-pre did incorrect reference counting, but also older sessions
had this issue. Perhaps due to ambiguities of matching playlists
by name in 5.x or session-format changes 3.x .. 5.x.
During session load, all earlier configure_processors() calls
were useless and not taking I/O into account! The Delivery ::pan_out()
needs _output I/O ports in order to correctly report the correct
port-count!
This worked in earlier versions because Config->map_parameters()
triggered [two] processor re-configs via ::listen_position_changed().
That behavior was changed in 1af123465c
This partially reverts 639dff3a7c. When loading a session,
the monitor-bus that was saved with the session is used.
This changes semantics of the monitor-section/config.
Config::set_use_monitor_bus(bool) is used to initiate a change!
Notification about the change is sent asynchronously by
Session::MonitorBusAddedOrRemoved
It is no longer possible to directly call add/remove_monitor_section()
and leave the session + config in an inconsistent state.
Trust that ::reset() works for all transport masters, and call it when engine is stopped. This way
the transport masters are ready to be called again as soon as the engine restarts.
This allows to special-cases session-specific control-surface state.
e.g. midi-learn.
Only restore midi-learned, session-specific, bindings when loading a
session with generic-midi enabled.
Also dis/re-enable generic-midi resets midi-learned, but no other
session-independent settings.
This also handles the edge case:
1) load global config, generic-midi = ON, w/ bindings.
state is remembered as cpi->state
2) load session-condig, generic-midi = OFF, cpi->state is retained
3) user enables the surface, cpi->state from (1) is applied.
-> invalid bindings applied -> fail
This also removes enums introduced to describe well-known parameters for Mixbus. Lookup now involves string
parsing every time, but this is not likely to be a notable cost.
* prevent duplicate names when pulling-in external sources
* drop "origin" after including external sources
* don't include unused playlists
(they may reference sources that are not included)
* likewise exclude unused regions
* Processor implement get_state(), classes derived from Processor
implement protected ::state() -- as documented in processor.h
* likewise for Route, Track: make ::state() a protected interface
* removal of "full_state", use explicit "template_save"
* use RAII/Unwind to skip saving automation-state
Generated by tools/f2s. Some hand-editing will be required in a few places to fix up comments related to timecode
and video in order to keep the legible
* requested_physical_in/out was unused
* input/output Autoconnect just overrides Preference/Config
(can be done by a template script)
* master_out_channels is kept for compatibility (allow to create
new empty session)
The vast majority of errors reported by users as
"Cannot configure audio/midi engine with session parameters"
have nothing to do with engine-parameters.
Loading a read only Session then making a copy with Save As and switch was
not allowing new Session to be saved as writable state was not updated.
Resolves: #7352
This prevents the node order from changing when the display order of the Routes
changes, which helps to reduce the amount of Session file change.
This is useful for testing and if keeping sessions under version control.
Resolves: #7327
eg. at the end of a loop, the session may already be playing the
beginning of the loop. The TransportLooped signal was emitted.
Yet due to playback latency, the audible frame is still at the end of
the loop.
To interpolate the playhead position the UI needs to be able to know:
Relying on the TransportLooped signal is not sufficient because it
does not take playback latency into account.