If the script doesn't provide a dsp_ioconfig() function, or if it does
not return a table of tables, provide an empty table of table as
default, which means a single configuration with default values.
Demote configurations if they have mismatched midi in or out with the
same mechanism as for audio, but with lower coefficients so that
mismatched midi has less influence than mismatched audio in selecting
the best configuration.
POLICY CHANGE.
Just refuse configurations without any output at all, and let the
remaining logic take care of selecting configurations with no audio
output if they make sense and there are no better configurations.
POLICY CHANGE: configurations with no output might now be considered
even if they have audio inputs (e.g. a pure pitch detector without audio
passthrough), whereas they were skipped before.
Instead of uniformly demote configurations with a non-matching audio
input count (using a penalty offset of 1000), also grade the
impreciseness of the configuration so that those with the nearest input
count are preferred. As for outputs, give a slightly higher handicap to
configuration with too many inputs with regard to the actual audio
inputs that can be fed to the plugin.
POLICY CHANGE: when only imprecise configurations are found the actually
selected one can be different (better) than before this commit.
Just make the code responsible for possible_in > 0 also handle
possible_in == 0 since it nearly does the same thing.
The only difference is that the possible_in == 0 case didn't check at
all for audio_in, essentially acting as if possible_in was audio_in.
There is thus a small POLICY CHANGE, but the selected configuration will
stay the same unless a better matching configuration is available.
Still no policy change, since when a configuration is chosen that would
have belonged to the second pass, then its penalty will be increased by
1000 and it will be selected only as last recourse.
This doesn't change the policy since configurations are given an
additional 1000 penalty if audio_in != possible_in, and will thus be
trumped by any "precise" configuration (unless the latter has 1000
excess or missing outputs which should be less than likely).
Instead of setting \imprecise at the end of the loop if a configuration
was found (which clobbered valuable information, see dae2406187), set it
each time a new configuration is chosen.
In the second loop that tries harder, resetting \imprecise also avoids a
previous "imprecise->set(AUDIO, 0)" to last even if another
configuration is chosen later.
Last but not least, it will enable correctly setting the midi input
count hoped for by the configuration.
Merge the cases in == -1 and in == -2 since those are both wildcards,
almost symmetric in the AU spec, and handled completely symmetrically by
the code here considering it accepts invalid or unspecified demands.
Also merge the cases in > 0 and in < -2 since they are handled exactly
the same as far as outputs are concerned.
That code modifies \imprecise if it is not NULL, but
- if a configuration is found, \imprecise will be set to in, clobbering
the tentative changes done here;
- if a configuration is not found, a last-resort loop will be run that
will set the same member of \imprecise, also clobbering our changes.
Remove it since it does nothing that is looked at before being
forgotten. A way to get the intended outcome will be introduced later.
...to later enable that condition truthiness to depend on the
loop iteration. The goal here is to prepare for the upcoming rewrite,
without introducing any policy change for now.
There is no behavior change because if all loop iterations are skipped,
then \found will be false, and with \imprecise being null the last
attempt will be skipped and we will return false.
Instead of doing an initial loop for detection of exact matches, then
letting the following loop set \audio_out yet ignore its value, merge
the two loops but give exact matches a negative penalty so that the
\audio_out value they set won't change afterwards.
No policy change.
Since can_replicate is true at loop start, and in the loop body there is
a break; after every can_replicate=false, there's no point to test its
value in the loop condition.
There is no code that read the set value in between the removed line and
its exact counterpart below. There is no similar duplicate in the
AudioUnit code due to the way AudioUnit handles midi.
The original LV2 state extension required that run() is suspended during
restore(). Ardour violates this rule, which can lead to crashes and
other issues.
The state extension has been updated to allow restoring state in a
thread-safe way by using the worker to enqueue state changes. This
commit supports that new specification, i.e. supports dropout-free state
restoration properly.
However, the bug with old plugins that do not use this facility is still
not fixed.
In some circumstances UI::flush_pending never returns, and all UI
interactive ends up being driven by
while (gtk_events_pending()) { gtk_main_iteration(); }
This has various implications depending on the caller and usually results
in a crash at session-close or exit.
Session::process() returns early with Session::_silent set to true. AudioBuffer::set_data()
was never set for (at least) the LTC output port. PortManager::cycle_end() calls
AudioBuffer::silence() which used to assume that get_buffer() must have been called. But it
was not, because that should have happened in Session::process().
So check AudioBuffer::data() and call get_buffer() if required.
The trim processor was moved to the front after the internal return was,
so the trim setting was applied before the signal coming from other
tracks/busses sends was mixed in. Change the order so that trim applies
to audio from internal sends as well.
To export a MIDI region to a file, the code used MidiRegion::clone()
since it takes care of creating a new file-backed source with the wanted
contents. Nevertheless, it had several side-effects:
- it created and registered a new region which is confusing to users
- it only exported notes that were in the region range, but didn't
remove the region start offset from MIDI events, essentially producing
a spurious silence at the beginning of the exported file (this is not
a problem for region cloning because the newly created region is made
aware of the offset and caters for it).
Add a dedicated code path for export, that uses the new offsetting
capabilities of MidiModel::write_section_to().
MidiModel::write_section_to() only wrote events to the given source if
those events had a time in the given range. Make it able to optionally
offset event times so that the start of the written range corresponds to
time 0 in the source.
Since lua functions are closures, C++ methods that pass arguments by
reference cannot be used directly. The previous approach (boost::ref)
failed with clang. Assume the following:
void foo (float&) { }
static inline float& bar () {
boost::reference_wrapper<float> r (42);
return r.get ();
}
foo ( bar () );
With gcc, "r" goes out of scope after foo's arguments are processed
and all is well.
But with clang, "r" already leave scope when *inlined* bar() returns.
Solution: allocate some user-data on the lua-stack to hold the reference.
There is no reference to this user-data so lua will eventually
garbage collect it.
(theoretically, creating the table which holds the return-values
could trigger an emergency garbage collection when memory is low and
free the reference just while they're being pushed to the table, then
gain FuncArgs<Params> already dereferenced them all as variable on the
C stack -- probably again compiler specific)
Code to check if we were to close to an edge (for window resizing) blocked all divider setting,
because it would be called with a current widget allocation of 1x1
This allows a TmpFile pointer to be either a Sync or Async (Threaded)
writer. As result we must be able to handle both RT and non RT processing.
Still, post-processing (normalization and encoding) should always
happen faster than realtime (freewheeling).
Since jack does not allow a client to change to freewheeling from within
the process-callback, the async-writer disk-thread FileFlushed is used
to initiate post-processing.
When flushing the buffers of Delivery processors owned by a Route/Track,
inner deliveries of PortInsert processors were missed since PortInsert
is not a Delivery subclass, but rather owns a Delivery as a private
member. Expose a flush_buffers() for PortInsert and call it too.
This is correct since (external) Send is a Delivery subclass, so that
just makes the send part of inserts behave as external sends do.
Route::no_roll(), Route::roll(), Track::no_roll(), AudioTrack::roll()
and MidiTrack::roll() all had the exact same loop for flushing buffers
of their Delivery processors. That was a lot of replicated code that had
to be kept synchronised by hand. Put that code into a protected method
Route::flush_processor_buffers_locked() which is called instead.
* add a threaded TmpFile Writer
* update API calls to that process_export_fw() can be used as
process_function
The idea is to re-use export infrastructure from normalization:
export to a tmp-file and then encode target formats after that.
Ardour takes the closest pin/port match yet still offers a plugin with
variable i/o access to all port-buffers.
the "reported" (user visible) pin-count now defaults to the actual
selected configuration (precise) and lua_dsp_configure() can
override it.