Ignore latency-updates while removing tracks.
remove_tracks() calls disconnect_all() which can trigger the backend
to perform a latency-recompute in a different thread (process thread).
That calls Session::update_latency() which iterates over all routes
including the one(s) to be deleted.
At the same time disconnect_all() may propagate Port::PostDisconnect()
leading to a lock contention.
(no crash just a lot of unnecessary work. remove_routes() calls
update_latency_compensation() which triggers a recompute if needed)
This prevents an extra call to "redisplay" from TAV::hide() which
triggers handle_gui_changes.
Visible TAVs are positioned using show_at() which unsets _hidden.
For every added Trackview/Mixerstrip, Ardour looks up GUI properties which
results in a total of 13 calls for the initial default items per track:
("height", "visible", "layer-display", "strip-width")
Since the tracks don't yet exist, the properties don't either.
Every lookup result in iterating over all all XMLNotes and for every
"Object". ->property ("id") and ->value () allocates memory.
Adding 64 tracks to an empty session results in 528293 string
allocations and deallocations in XMLNode::property() taking ~30%
of the track creation time.
This commit XMLnode's const method to prevent memory allocation
and caches a pointer to the XMLNode* to skip iterating over object
state.
* all API calls use session-time (allow region-lists)
* per-region transients are separated in
- Onset (Rhythm Rodent, Aubio)
- User-added
- internal/source (QM), used as fallback for next/prev (read-only)
This commit swizzles (replaces) NSView::displayIfNeeded to allow us to stop redraws of plugin
windows if the Glib idle timer fires less often then every 40msec. The next 10 plugin redraws
(for all plugin windows combined) will be skipped. Heuristics will likely need some adjustments
This prevents a memory leak: The session is closed.
The session-butler drops memory pool trash. The Engine keeps running.
Once the AudioEngine is taken down (sample-rate switch, or at exit),
the backend process-thread is terminated but there is no trash-can anymore.
If there are unprocessed SessionEvents, this calls
free_per_thread_pool() -> cp->parent()->add_to_trash (cp).
"parent()" in this case the trash-can the butler emptied.
When adding a processor, the processor may add ports leading to
a call to jack_port_register(). while Ardour holds a WritertLock on the
processor-list (this commit removes this WriterLock).
with jack2 that results in a graph-reorder callback (WHY?)
jack2 issues that graph-reorder in a separate thread BUT
port-registration does not return until the graph-reorder is complete.
On Ardour's side, graph_reordered() calls Session::resort_routes ()
which eventually checks Route::direct_feeds_according_to_reality()
which needs a ReadLock on the processor-list to check I/O.
Since jack_port_register() does not return, this constitutes a deadlock.
THE ACTUAL PROBLEM IS JACK2's THREAD DESIGN!
Why does jack_port_register() trigger a graph-order in jack2?
No connections are made.
..and why does it block jack_port_register() from returning if
that graph-order callback is in a different thread?
http://pastebin.com/DZANXJLz