Creating an iterator on a MidiModel (Sequence) creates a read-lock on the same,
which exists until the iterator is destroyed.
This new designs renders the model/source to an RTMidiBuffer, then atomically
swaps in a new RTMidiBuffer in an RT context.
Not yet implemented in this temporary branch is handling required
state-changing messages when the buffer is swapped.
84e38b4c65 made the same change for FP16.
It has apparently not been necessary for FP8 so far, because backends
have happened to report "Port 1" before the control port. But that is
not necessarily the case. It failed for me when playing around.
Change FP8 handling to also not make assumptions about the device order
returned by the backend.
These days it only produces false positives (locate at start
of session export).
We leave `ENSURE_PROCESS_THREAD` in place, since it may
come in handy at some point (eg. static analysis, documentation)
previously, _chunksize =
```
minimum_disk_read_bytes / sizeof (Sample)
```
can become larger then actual allocated ringbuffer:
```
audio_playback_buffer_seconds * sample-rate
```
In which case the buffer was never filled.
The disk writer has similar issues
This fixes an issue when undoing region fades.
Particularly but not limited to the following:
1. select a region and split it in the middle
2. switch to range tool. make a range selection across the split
3. Edit > Fade > Fade range seection (or press `/`)
4. Undo
Previously the fade-out of the earlier region was not undone.
When some other transport related session event (anything that
requires non_realtime_work_pending, e.g. PostTransportOverWrite)
coincides with SessionEvent::AutoLoop, the auto-loop event
was removed from the main event queue and executed as one-shot
immediate event.
While looping the AutoLoop event needs to remain on the main
event queue.
`butler_transport_work()` may be called for various reasons,
notably PostTransportOverWrite. At that point in time the
transport may still be rolling or stopping with rtloc already
set.
This can cause DR::Underruns since seek clear the entire
disk reader buffer.
This is needed to properly decrement "should_do_transport_work".
After a seek the DR:_pending_overwrite flag will have been
cleared, so not much extra work happens here.
The left edge of a region on the the editor is rounded to be
on a pixel. When zoomed out, the position corresponding to that
pixel is not usually identical to the region's position().
We need to correct for this as best as possible, while keeping
peaks aligned to pixels.
Previously loop-wrap around asked the butler to perform
a unnecessary seek operation next time it is summoned.
If the butler is then summoned for a PostTransportOverWrite
event, the seek causes a DR::Underrun.
The signal would be emitted while the session was temporarily renamed,
making it appear that we had switched to the new session, despite instructions
not to do so. We had not actually done so, but the saved-as name would show up
on window titles.
Popup Dialog Windows never unset the modal flag.
e.g. Session > Save Snapshot & switch.
Furthermore a 2nd dialog was able to get the menu stuck
forever (e.g. Snapshot & Switch .. -> Replace existing?
In order for the Filechooser Location widget to work two
things need to be setup, which only the FileChooserDialog
does:
* subscribe to Widget's "response-requested" signal
* call should_respond () hook from top-level window's
default handler.
The Location Entry emits "activates-default". In case of
the Dialog, that calls the dialogs response callback,
which then calls ` _gtk_file_chooser_embed_should_respond`.
That handles changes made by the user to the location entry.
-=-
Gtk::FileChooserWidget does not handle this, "response-requested"
signal is not exposed, nor is _gtk_file_chooser_embed_should_respond
available outside Gtk.
This change at least selects the file in the treeview, which
allows further handling, without interfering with FileChooserDialog's
behavior.
This reverts
* e48d97ed69
* 98c906b733
* 0cf73d459b
because the C++ API std::map:at can throw and exception
was not implemented (and also deemed excessive for the
case at hand). Also an explicit API for *p*plugin_pin
mapping is preferable and facilitates debugging.
When handling the `/set_surface` command, the code would set
plug_page_size to the new value first, and call `sel_plug_pagesize()`
later. The latter then sees the page size is already the same, so it
leaves it unchanged and also does not send the page size to the
OSCSelectObserver object. In practice, this means that only the default
plugin page size from the preferences or set with
`/set_surface/plugin_page_size` take effect and values set with
`/set_surface` are ignored.
Exactly the same thing happens for the send page size.
This code has been like this since it was first introduced in comit
9c0f6ea948 (OSC: Allow set_surface to set send and plugin page sizes.,
2017-06-13)
This commit fixes this by omitting the first assignment.
Before this commit, OSCSelectObserver would read the feedback value when
it was created, but then never update it anymore. In practice, the
OSCSelectObserver is created on startup, and when the surface connects
and configures feeback, this value is not applied.
For example, when sending `/set_surface` with a feedback value of
4 (Send SSID as path extension), `/strip/*` would get their ssid put
into the path, but `/select/plugin/*` messages would not have their
parameter id in the path. When setting the corresponding checkbox in the
default feedback preferences, it is applied as expected.
This commit passes the new feedback value to the OSCSelectObserver
instance whenever it changes, which ensures the value is applied as
expected.
MidiTrack::restore_controls is triggered by SessionLoaded
event. Yet MidiControl::actually_set_value checks if
_session.loading() is true and postpones sending actual
events to the synth (which may not be fully loaded).
Before 5d02970de8, Session::post_engine_init unset
"Loading" flag early on, so "loading" was already unset
by the time `SessionLoaded` was emitted.
this fixes issues with MIDI region recording, which otherwise never
goes through the code path required to "fix" the nascent data into
sources and regions.
This fixes a crash at exit for some Linux VST3s when Ardour
calls ::release_factory() before unloading the module.
The plugin will then also call unref the hostContext. Previously
the lookup interface for the host context was provided by the
plugin; which at that point in time was already deleted.
Previously this caused deadlocks (read lock while holding
write lock), and also not dropped references of plugins.
Ideally undo/redo of FX unrelated region state
will not re-instantiate plugins; we can optimize this later.
See also a1ba561cc5. JACK2 and pipewire unconditionally
report 32kB, Ardour internal backends report 8kB, also
independent of the buffersize.
While jack1 by default announces the audio buffersize.
A sensible value assumes that the GUI reads the FIFO at
a least 25fps, while also allowing MIDI ports to merge
data (hence 2 * raw_buffer_size). Yet limit to 64k per track.
Since RegionFx are significantly simpler compared
to processors, missing plugin state can directly be handled
in the implantation without creating a subclass similar to
UnknownProcessor.
Previously there was a race condition. DiskWriter::run()
cleared the gui_feed_buffer before writing new events.
If the GUI thread had not yet picked up the events by then
they were not displayed. Furthermore due to the try-lock,
some events may have been written to the buffer in the first
place.
This fixes missing events (notably stuck notes) in the red
record box while recording MIDI.
_output latency was not used for those. Processor automation
was not affected.
This also fixes the visual offset of automation vs buttons/slider
when the transport is not running.
When removing instances from some RCU managed list or vector,
they can still live on as shared_ptr references on the
RCU's dead wood stack.
In many cases this is not an issue, in these cases it's prudent.
see also 44610c7877
This riffs off the previous commit, a simple way to replay
ctrl events without re-evaluating plugin automation line.
There may be a better way to handle this (e.g. replicate the
plugin for display only, evaluate on the fly in the UI thread)
Short of redesigning our disk-reader/playlist/region infrastructure
this is likely a sucks-least compromise for the time being.
This can happen with VST2s (e.g gvst) and some JUCE based plugins.
Previously that lead to a "programming error: no per-thread pool"
when the DR queues a overwrite buffer session-event.
This is mainly for the benefit of Mixbus, where input_latency
is not propagated upwards from the master bus (no direct
connection).
In Ardour's case _worst_input_latency >= _worst_route_latency
unless a given track with latent plugin is not connected.
Previously looping became out of sync (normal playback was not
affected) when a track had a latent plugin.
Mute and Panner are the only automatable Route owned controls
(that are not managed by a processor). So they need special
casing to be moved when moving a region.
This replaces rule #17, 27, 43 and 59 on
https://manual.ardour.org/appendix/monitor-modes/
"Meter (What you see)" changes to 'Disk (Audio)'
aka "what you hear" in those cases.
This way "what you see" is always "what you hear".
Monitoring inputs is more conveniently done using
the Recorder Page.
The core selection can be (a) stripables (b) automation controls (c) possibly a combination of both
Any given selection op might pass (a) or (b) or (c), so we need to handle the
case where (a) is null.
By default timecode.rate = 30. When 30fps LTC is received,
::detect_ltc_fps() never returned true (FPS changed), and
the TransportMaster never entered "locked" stage.
We now have two basic methods for CoreSelection
* when selecting a stripable, use ::select_stripable_and_maybe_group() with
appropriate arguments to cover the group selection aspects.
* when selecting an automation control that is part of a stripable, call
::select_stripable_with_control()
The old, more simply named methods (set/add/toggle etc.) have all been
made private, and their internal implementations changed somewhat.
This commit includes changes to control surfaces that use CoreSelection directly.
In livetrax, where RF64 is one of two file formats, people frequently end up
with files named .rf64 that are actually .wav due to the libsndfile
header file downgrade. We want to avoid this, and this seems like
a more common case than people generating actual RF64 files that
(now) will be named .wav
see also 2e23ec4422. This fixes a bug where some ports
remain in used (shared_ptr<Port>) by the RCUManager, even
after the port is removed from the port_map.
This can lead to issues when the port is re-registered later.
GCC 14 educates us:
In file included from ../libs/ardour/ardour/io.h:44,
from ../libs/ardour/ardour/route.h:50,
from ../libs/ardour/ardour/session.h:92,
from ../libs/ctrl-interface/midi_surface/midi_surface.cc:30:
../libs/ardour/ardour/port_set.h:92:37: warning: template-id not allowed for constructor in C++20 [-Wtemplate-id-cdtor]
92 | iterator_base<PS,P>(PS& list, DataType type, size_t index)
| ^~
../libs/ardour/ardour/port_set.h:92:37: note: remove the ‘< >’
This works around an issue with some embedded plugin windows not being
properly restored when the window is restored after being minimized. It
also prevents zooming (full-screen) display of dialog windows.
Also recent macOS allows to maximize Windows even if they are not
supposed to be resizable (also causing issues with some plugins).
1. do more to ensure that we do not call MidiSurface::begin_using_device()
multiple times without ::stop_using_device() in between. This reduces the risk
of duplicate signal handler connections being made (it might even eliminate it).
2. Notify all control surfaces when MIDI connectivity is established AND
disestablished. This gives them a chance to update their notion of their
current connection state. This can be important with JACK across zombification,
but also likely across backend stop&start.
These changes currntly only impact classes derived from MidiSurface but
something equivalent is required for all control surfaces
On macOS popping up a menu with a position function that leads the menu to be
under the mouse pointer generates the same initial set of enter events as on
linux, but this is then followed by some leave events and then a repeat of the
same set of enter events.
this exposes what appears to be a logic error in gtk_menu_enter_notify().
Nonlinear enter events (i.e. where the menu pops up under the mouse, so the
mouse was never actually moved into the menu's window) should not cause a reset
of priv->seen_item_enter. This value, when true, is used to force the next
received button release event to be handle as an menu activation event. This
should only happen when the mouse has actually been moved by the user into the
menu (as already indicated in existing comments). The value has this effect by,
on the next enter event for a menu item, if already set, forcing
menu->activate_time to zero, which in turn will cause menu activation on button
up/release.
This bug doesn't appear on Linux (or Windows) because the event sequence
associated with a menu popup is different. The lack of another set of enter
events means that menu->activate_time is never reset, and so the behavior is as
expected.
This change makes the setting of priv->seen_item_enter be idempotent with
respect to non-linear enter events, which I believe is the intended behavior.
This fixes an issue on Windows, where UI::run can dispatch
a signal that ends up via cross-thread channel at the surfaces'
BaseUI::request_handler. causing a segfault.
First see 31c6f66d9b and 5cb6e1046b.
It worked previously due to `AutomationControl::get_value`
evaluating automation, which was removed in 5cb6e1046b
in favor of properly using latency compensated evaluation.
However due to 31c6f66d9b, fader and trim automation were
never evaluated on locate, only during playback via
`Amp::setup_gain_automation`.
This fixes a case where gain is incorrect after a locate.
The amp still has the gain from before the locate, and when starting
playback ramps to the new gain.
The MIDI specification makes it quite clear that when a receiver
receives the MSB of a 14 bit controller value, it should consider
the LSB reset to zero. This has been an error in Ardour for many,
many years, though likely of little consequence
This removes the _io_lock in favor of a RCU.
The reason for this change is to ensure data structure
consistency, notably iterators. Previously adding/removing
ports invalidated iterators, which caused [rare] crashes,
since IO::ports() simply returned a PortSet reference.
(This breaks API)
When double-clicking to edit a fader value three button press
events are created:
1. GDK_BUTTON_PRESS
2. GDK_BUTTON_PRESS
3. GDK_2BUTTON_PRESS
The first two start an Editor Drag, which later crashes in
Editor::mid_track_drag() gtk2_ardour/editor.cc:7067