Before, the .cue file could end up with a mix of latin1 and utf-8
encodings. Utf-8 works better for many things, but that doesn't matter
when the .cue file has to be in latin-1.
Play loop, change loop-location, undo.
Undo calls Locations::set_state, takes a writer-lock,
and calls Location::set_state which emits a Changed signal.
This triggers Editor::location_changed, and if loop-location
changed while looping, update_loop_range_view() queries the
loop location, taking a reader-lock.
This leads to a recursive lock, RWLock::ReaderLock after
a RWLock::WriterLock does not cause a deadlock, however
releasing the ReaderLock effectively also unlocks the WriterLock.
This leads to a deadlock next time a writer-lock is acquired.
'unbang' is better described as a mouse-up or button-release event
* if launch-style is Gate or Repeat, then UnBang will stop the playing clip
* in other launch-styles, UnBang is ignored
some prior code using UnBang will change to
stop_quantized() or request_stop()
Grid controllers will largely want to access clips in the order they appear on the Cue page
It is up to the device (and/or its ControlProtocol) to handle banking
normally we operate on TriggerPtr's which are a safe way to track
trigger lifetime, safely modify their properties, and launch them.
bang_trigger_at() is a convenience function to look up a trigger by index,
and launch it, in one step. Potentially useful for control surfaces.
We now try to get to the right location within the MIDI data and continue
playing, rather than pretending that we reached the end.
This also fixes a thinko that caused only the first few notes of a
MIDI trigger to play.
This may also solve cases where due to length, sample rate and tempo
settings, a trigger finished precisely on a ::run() call boundary.
* allow to update IR data
* allow to use mono processing in base-class
This is handy for FIR (Readable/ROM), and operating directly
on local data (ratherer than mapped buffers)
Usually C++ class instance has the same mem address as its first parent.
LuaBridge uses this to for derived classes. A TemopPoint instance has
the same address as its parent Tempo. However due to virtual inheritance
this was not the case due to a lack of virtual d'tor.
Now the following Lua code works correctly
```
tm = Temporal.TempoMap.read()
tp = Temporal.timepos_t (0)
print (tm:tempo_at(tp):note_type())
```
Previously the last line failed calling Tempo::note_type()
on a TempoPoint instance, due to memory offset e.g.
TempoPoint: 0x600000ff90e0 Tempo: 0x600000ff90e8
For some reason applying the property change
plist.add (Properties::start, std::numeric_limits<timepos_t>::min());
does not correctly reset the offset of the newly created region.
The during trim-front, the call order is
1. Region::set_position_internal
2. Region::set_length_internal
::set_position_internal sets `_last_length.set_position (position());`
but the later call ::set_length_internal does `_last_length = _length;`
This sets last_position() == position(), and later Region::mid_thaw()
does not call Region::recompute_at_start().
Region gain envelope was not updated.
see also 00a1b7cb24 and 13d10582f0