Region positions were updated in the GUI, before the playlist
was catching up.
The butler thread reads a region using the region's new position,
but the playlist's old range.
Thread 1 (GUI)
```
#22 ARDOUR::Playlist::notify_layering_changed()
#26 ARDOUR::AudioPlaylist::region_changed
#27 ARDOUR::Playlist::region_changed_proxy
#35 ARDOUR::Region::send_change
#36 ARDOUR::Region::set_position
#37 RegionRippleDrag::remove_unselected_from_views
#38 RegionRippleDrag::finished
```
LayeringChanged() also triggers DiskIOProcessor::playlist_modified
which schedules a pending-override and summons the butler.
Note that when moving only a few regions the butler starts after all
updates have been completed.
Butler thread:
```
#4 ARDOUR::AudioRegion::read_at
#5 ARDOUR::AudioPlaylist::read
#6 ARDOUR::DiskReader::audio_read
#7 ARDOUR::DiskReader::overwrite_existing_audio
#8 ARDOUR::DiskReader::overwrite_existing_buffers
#9 ARDOUR::Track::overwrite_existing_buffers
#10 ARDOUR::Session::non_realtime_overwrite
```
Region read fails:
```
libs/ardour/audioregion.cc:503 assert (position >= _position);
(gdb) p position
$1 = 1312000
(gdb) p _position
$2 = {<PBD::PropertyTemplate<long>> = {_have_old = true,
_current = 1336000, _old = 1312000} }
```
The DraggingView's time_axis_view (index) is set to the size of _time_axis_views
in ::motion() near line 1149. This makes it invalid as index into the vector.
see also 25c0bd9274
play, locate, play resulted in the video-monitor showing
the target frame shortly, and play a few frames from the old
location.
This was due to locate happening async. Click to locate
directly sends the new location:
```
VideoTimeLine::manual_seek_video_monitor
ARDOUR_UI::update_transport_clocks
CursorDrag::fake_locate
CursorDrag::start_grab
DragManager::start_grab
```
CursorDrag::finished unset _dragging_playhead before the
call to resuest_locate(). Meanwhile playback continues.
This is an initial work-around for signal emission with
Playlist:region_lock held:
Playlist::duplicate() takes RegionWriteLock() and then calls
RegionFactory::create(). The newly created region does NOT have
property-changes suspended, and the RegionFactory can change
region-properties which results in signal-emission.
This in turn can lead to a call Editor::session_gui_extents()
-> ARDOUR::Playlist::get_extent() -> Playlist::RegionReadLock
which deadlocks: https://pastebin.com/84rSbsA3
Eventually we need a mechanism to create regions with
->suspend_property_changes() and add it to the playlist's
thawlist (pass a thawlist to the region-factory).
Playlist changes do not include region-property changes.
When inserting a region, position(s) of other Regions may
change and those changes have to be recorded explicitly (for now).
see also RegionRippleDrag.
The undo command needs to be started before calling
playlist->add_region() because that may move automation
or include ripple changes. see the following backtrace:
```
UndoTransaction::add_command
ARDOUR::DiskReader::move_processor_automation
ARDOUR::Route::foreach_processor
ARDOUR::DiskReader::playlist_ranges_moved
ARDOUR::Playlist::flush_notifications
ARDOUR::Playlist::RegionWriteLock::~RegionWriteLock
ARDOUR::Playlist::add_region
Editor::bounce_range_selection
```
Except. it seems automation is moved incorrectly in this case..
Some plugin UIs, particularly those that cannot be resized
unset `autoresizesSubviews`. Since the plugin-view is re-parented,
the host has to directly set the view's size.
However some plugins have multiple child views, apparently
for off-screen pixmaps (e.g. UAD plugins). Those additional
should not be resized (or re-stacked).
e.g.
Reason-Rack
view 0x7fe27e44e570 @ 0, 33 834 x 804
view 0x7fe288aa3770 @ 278, 268 278 x 268
UAD Tube-tech
view 0x7fe270a9cbf0 @ 0, 33 1160 x 374
view 0x7fe28883d030 @ 0, 0 1160 x 374
view 0x7fe2888546e0 @ 0, 0 1160 x 24
see also aef366c156https://discourse.ardour.org/t/uad-plugin-will-not-load-shows-as-expired-when-its-not/105756/5?u=x42
Preferences is a tabbable, a leftover artifact of when it was, in fact, intended to be a tabbable. Rather than
re-engineer this right now, add a key event handler so that Primary-w works for this just like other dialogs
When switching to Semitones, round speed to nearest semitone.
This fixes an issue when rolling forward at < 25% which is
less that -24st and then scrolling right (increase pitch).
The result may still be < -24st and playback reverses.
When changing max-speed, directly constrain speed.
Previously it was not possible to return from reverse playback
since left-scroll decreased pitch, even during reverse playback.
This also fixes an edge-case when quickly scrolling through
zero. use_shuttle_fract() ignores rapid events, map_transport_state()
can round speed to zero and next scroll-event set the default +1st
speed (really should have been 0st).This is solved by starting at
-24st, similar to how percentage does not start at 100%.
When there are no input ports at the time the engine starts
running, MonitorInputChanged signal was not subscribed to.
This breaks AFL solo. This happens e.g. when re-starting the
engine with ALSA slave devices.
../libs/pbd/pbd/string_convert.h: In function 'std::string PBD::to_string(T) [with T = long unsigned int]':
../gtk2_ardour/foldback_strip.cc:581: instantiated from here
../libs/pbd/pbd/string_convert.h:238: error: 'long unsigned int' is not a class, struc
* Insensitive route-ops menu when track disabled
* Re-order route-ops to match mixer-strip
* Add number Label to foldbacks
* Set spacing for consistent look/feel
When using chained sends, only show the direct parent:
track A -> bus 1 -> bus 2
Showing sends feeding "bus 2", previously also displayed
"track A". However only "bus 1"' mixer-strip changed to show
the send controls.
We should not propagate displayed deliveries upstream, since
there may be ambiguities. There could be an additional send:
track A -> bus 2
* Consolidate access modifiers
* Remove all public member variables
* Only expose required functions, use private
whenever possible
* Rename private members, prefix underscore
* Remove cruft
This resolves ambiguities of overloaded non-virtual methods
that used shared protected variables (send_blink_connection).
It fixes "show sends" of foldback busses (spilling the send
controls) and allows for showing showing other sends directly
without first disabling it.
This fixes some related issues with inheritance and
signal propagation.
Also since foldback-busses are not selectable AxisViews,
various keyboard-shortcut operations cannot be performed
from the mixer-context. However the processox-box itself
provides these actions for the fold-back bus.
Remove unused code that was copy/pasted from mixer_strip.cc
which is not needed for foldback strips. Notably alternative
delivery display mode (aux-sends).
This GTK button style is out of place in both contexts.
Furthermore it is inconsistent to not have the same button
in the editor (there is a dropzone).
* un-hardcode button numbers, use portable modifier API
* allow to toggle Send bypass with middle-click
* add support for delete-operator
* Only act on single-click press
Prefer to reuse spill logic from the mixer-ui.
This allows to spill routes directly after spilling
foldbacks. Previously that resulted in FB "show sends"
to keep flashing even then no foldbacks were spilled anymore.
It also simplifies various aspects of foldback prev/next
logic.
The mixer gain-entry selects all when the entry is focused
(see ArdourWidgets::FocusEntry). Due to the selection there is
no visible cursor, and it was not obvious that the entry
has focus. Also moving the mouse outside of the strip drops focus
without any indication.
This combines SessionEvent per playlist. Now per change
there are "only" two SessionEvent::Overwrite events
queued per playlist in the GUI thread for later processing
the Butler.
These are triggered by Playlist::ContentsChanged()
and Playlist::LayeringChanged(), both of which trigger
DiskIOProcessor::playlist_modified.
(Previously there used to be two per region)
"T: " prefix isn't very useful. in music-notation the note
symbol is established: ♩ = <bpm> or ♪ = <bpm>.
This fixes an issue on Windows, where those note symbols are
not available in the default unicode font. There "1/4" is used
which adds two extra monospace chars leading to cropped text.
The initial calls in `we_have_dependents()` was redundantly setting
all widows to "Hidden", before the actual state was known.
tabbable_state_change() is initially called for all Tabs:
ARDOUR_UI::setup_windows -> add_to_notebook() -> attach(),
or for detached windows Tabbable::set_state() -> hide_tab().
Step_up/down_through_tabs used window visibility to determine
candidates. This incorrectly considered detached visible tabs.
Detached windows cannot be cycled to.
This also addressed an issue where tab-buttons state was
incorrectly unset what unrelated tab state changed.
ImplicitActive of the currently active tab is now retained
when some other window is attached/detached.
This add support for special-cased automation controls
(Fader, Trim, Panner, Mute) and spills their automation-lane
on touch.
It also features a small internal API update directly mapping
CheckMenuItem. See also bd8c26a059
playlist->partition() calls DiskReader::playlist_ranges_moved()
which may add Panner and Fader automation state changes.
The reversible command has to be started before calling
playlist->partition(). Simply collecting playlist->rdiff() after
the fact is not sufficient.
Since switching to StartupFSM, the GUIIdle signal isn't available
connected at application start. The splash-screen was blank until
the main UI was up.
"Ardour is ready for use" was the only visible message.
This fixes crashes with plugins calling setDirty() when the
UI is closed. `plugin` has already been reset before
the actual window is closed:
`PluginUIWindow::~PluginUIWindow()` runs, and destroys the window,
here `~VST3NSViewPluginUI ()`. This closes the VST3 view, which
triggers a `VST3PI::setDirty`.
At this point in time `~PlugUIBase()` has not yet run, so all
signals are still connected.
setDirty() ends up calling PlugUIBase::update_preset_modified()
which access `plugin` pointer, which is NULL.
curl_free() is to be used for data allocated by
curl_easy_escape() or curl_easy_unescape() in libcurl.
This is unrelated to realloc/free in WriteMemoryCallback().
MidiRegionView::select_notes() may call MRV::add_to_selection
which may call editor().get_selection().clear ();
This in turn clears the pending_midi_note_selection, invalidating
iterator.
This bug was introduced in 7cf435a876 (6.5.148)
PortGroupList::gather() first adds UserBundle ports to
`system->add_bundle (*i, allow_dups);`
That can include ports that are already associated with the
current bundle. The port in this case has the Bundle's name.
Those ports are later removed in BundleEditorMatrix::setup_ports
`_ports[OTHER].remove_bundle (_bundle);`
However we do need to show physical ports by their name, even
if they're identical to the already associated bundle to allow
disassociating them.
Clean up internal API confusion
- can_add_channels_proxy () -- checks presence of io
- can_add_channel_proxy () -- checks io->can_add_port()
UserBundle don't have a PortGroup::_bundle reference
that can be used to lookup the IO via io_from_bundle().
While BundleEditorMatrix::can_add_channels_proxy() was overriden
to allow adding I/Os, can_add_channel_proxy() later prevented that.
This further prevents removing the last port, preventing empty bundles.
This fixes an issue with the connection button still showing
the name of a Bundle even after deleting it, or displaying an
old name after renaming a bundle.
With bundles `ports_are_inputs()` indicates inputs that Ardour
can write to (data sinks, for playback).
BundleEditor::input_or_output_changed () set this correctly.
The rec-arm circle diameter is given by 0.5 * min (width, height).
For mono tracks the diameter is limited with the height of the
track. When more channel meters are visible the height increases and
the rec-arm circle grows.
The solution here is to constrain the rec-arm button width to its
minimum and not grow to have the same width as other buttons.
This also changes the default meter-height so mono and stereo tracks
have the same height (with default scaling).
The calculation to round the distance to seconds has to be performed
using floating point maths, not just the result being cast to double.
The time-granularity must not be zero.
* Shorten long labels
Those increase the x-offset for the data table column on the right.
* Shorten some long ComboBox texts
* Reduce min. slider controller width
* Tag some long labels and dropdowns that are currently the bottleneck
* Split "Signal Flow" pages to reduce height requirement
-> Signal Flow & -> Solo/Monitoring
The latter is just control logic, no signal flow changes.
* Group CPU/FPU performance Options
* Move Region-Analysis to Metering (it is not performance related)
* moved some wrongly-parented items into a more sensible location
(import & export options for example)
* broke some busy pages into separate sub-tabs: Size+Scale,
MIDI Port configuration, Timecode Generators
* added "Performance" tab to consolidate some of the tweakier prefs
* moved the order of tabs around so the "indented" ones were not
so intermixed with the non-indented ones
code changes:
bbt_ variables don't need to be global to editor; we only use these in compute_bbt_ruler_scale now anyway
drive the ruler with the same coarse-ified bbt_ruler_scale that we calculate for the snap grid
The location name is only pushed to the backend during
ExportTimespanSelector::add_range_to_selection() which in turn
is only called when timespans are updated.
Mixer_UI::show_window(), Editor::use_own_window() use
`show_all()` and the fixup items that should be invisible.
This involves a call to `parameter_changed ("show-group-tabs");`
Previously it was possible to open the multiple IOSelectorWindows
from multiple locations: editor-mixer, mixer, track/bus inspector,
track header context menu, etc. for the same port.
This allows to re-use playlist editing in all RouteUI derivatives,
not just the main editor time axis header.
The change is mostly a NO-OP, simply moving methods from
RouteTimeAxisView (is-a RouteUI), to RouteUI.