Currently when a GhostRegion is deleted by its "parent" RegionView it emits the
static GhostRegion::CatchDeletion signal which is connected to the
RegionView::remove_ghost method of every RegionView instance.
With a static GhostRegion::CatchDeletion signal a particular test session
causes 31 Million calls of RegionView::remove_ghost on Session deletion and the
session takes 70 seconds to close with a debug build.
The lifetime of a ghost region is tied to both the TimeAxisView(TAV) and
RegionView(RV) in that when a RegionView is deleted all GhostRegion instances
associated with the RegionView should be deleted or when a TimeAxisView is
deleted all ghost regions that are contained in the view should be deleted.
This means that there needs to be notification between GhostRegion and both
classes. Instead of using a signal for this as we know there are only two
listeners and GhostRegion already holds a reference to the TimeAxisView, also
take a reference to the parent RegionView in the GhostRegion constructor and
use it to notify the RegionView when GhostRegion destructor is called so it can
drop any references it holds.
Using a direct function call in the GhostRegion destructor to notify the
TimeAxisView and RegionView "parents" brings the unload/close time down for the
test session from 70 seconds to 4.5 seconds.
The GhostRegion also references canvas items that are added to the TimeAxisView
canvas group or at least a canvas group that it manages. So when the
TimeAxisView is destroyed and the canvas group that is the parent of those
items is destroyed, the GhostRegion's canvas items will also be
deleted/destroyed by the parent canvas item/group. This means the GhostRegions
must be destroyed when the TimeAxisView they are contained in is destroyed or
there will be dangling references to canvas items that have already been
deleted and trying to delete them again will be bad.
NoteBaseDeleted signal is static so each MidiRegionView(MRV) gets notified
about the deletion of each NodeBase instance even if it is contained in another
MRV
The NoteBase and MRV classes are currently coupled anyway, so this change uses
the reference to the MRV parent to directly call the parent when the NoteBase
is deleted. This is all in the GUI thread so I'm not sure why a PBD::Signal was
being used?
If the MRV class is the only reference holder to the NoteBase class
then I'm not sure if a callback is needed, perhaps the MRV should just remove
the note from the selection before deleting it but I'm not that familiar with
the code.
Signal emission/calls static NoteBaseDeleted signal vs direct with 10540
NoteBase instances.
static:
After Load Session: 6360638
After Unload Session: 12221026(5860388)
direct:
After load Session: 10540
After unload Session: 21080
Session Load/Unload time in master, debug/release with ~10000 Notes(seconds)
Load Debug: 32, 26
Unload Debug: 83
Load Release 32, 20, 42
Unload Release 26, 25
Session Load/Unload time with direct call debug/release(seconds)
Load Debug: 21.7, 18.1
Unload Debug: 69.4, 71
Load Release: 22.6, 13.4, 17.7
Unload Release: 24, 23.5
This is not a large Session, 1500 regions, 10000 notes so there is probably
some other funky stuff going on that needs fixing.
This moves MIDI channel filtering into a reusable class and moves filtering to
the source, rather than modifying the buffer afterwards. This is necessary so
that the playlist trackers reflect the emitted notes (and thus are able to stop
them in situations like mute).
As a perk, this is also faster because events are just dropped on read, rather
than pushed into a buffer then later removed (which is very slow).
Really hammering on mute or solo still seems to produce stuck notes
occasionally (perhaps related to multiple-on warnings). I am not yet sure why,
but occasional beats always.
During DnD, the region uses the 'old/current'
midi_stream_view()'s range and its position/height calculation.
Ideally DnD would decouple the midi_stream_view() for the
region(s) being dragged and set it to the target's range
(or in case of the drop-zone, FullRange).
but I don't see how this can be done without major rework.
For now, just prevent visual bleeding of events in case
the target-track is smaller.
This is debatable, the "sustained until mouse release" behaviour is handy
sometimes, but this way seems like what most people probably want.
Also, this "fire it and forget it and let it delete itself a bit later" thing
with MidiPlayer makes me nervous. I guess it's unlikely someone manages to
select a note then delete a track within 100ms, but, well...
This avoids stuck notes if active notes are edited, but without stopping all
active notes in the region on any edit as before.
This implementation injects note ons in places that aren't actually note
starts. Depending on how percussive the instrument is, this may not be
desired. In the future, an option for this would be an improvement, but there
are other places where "start notes in the middle" is a reasonable option. I
think that should be handled universally if we're to do it at all, so not
considering it a part of this fix for now.
Fix several other cases where a single mouse click could cause several
(not nested) selection ops.
Fix missing selection memento for midi notes and midi commands.
Rename some variables.
Fix random style issues.
The reasonable value 1 tick doesn't seem to work here, presumably it gets lost
in rounding conversion somewhere. Instead use a really small power of two
reciprocal. Once we use actual beats and ticks we can fix this to be a minimum
of one tick (the actual minimum length for a note).
... almost. There are some artifacts when you zoom out while recording that I
can't figure out, but whatever.
Also fix performance issues caused by last attempt at rec display while zoom.
For example, if you're in a note and something about the mode changes, it's the
underlying region context that needs to change. So, seems we need a stack of
entry contexts to deal with this sort of thing.
Switching in/out of smart mode still doesn't update immediately because we
don't have the y-coordinate needed to update it.
combines selection related editor properties with the current editor selection.
The related editor properties are:
mouse mode,
zoom setting,
left frame of the canvas,
y origin of the canvas.
Selection state now includes region views (storing the underlying region id)
and time.
This patch also fixes a region mute undo bug.
This commit changes some color names, nuke your theme. This isn't quite ideal
yet, but takes some steps towards where I think things should go aesthetically:
Make automation tracks/regions colors correspond to their parent's type.
Make selected MIDI notes outlined in red like most everything else, and scrap
separate min/mid/max fill colors for selected MIDI notes.
Color automation ghost MIDI notes based on original note color.
Try to kill 90's looking brightish gray gradients in general.
Unfortunately we store the state of models as simply model, so if there's ever
duplicate model names, we're somewhat screwed, but this makes the (previously
unmanageably huge) menu usable, while retaining the "model name as global
identifier" state unmodified.
When entered, the keyboard is grabbed when the selection becomes non-empty, and
ungrabbed if it becomes empty again or the region is left or the user switches
out of internal mode.
This fixes scroll in internal mode and note moving with arrow keys. Also frees
up useful keybindings when there is no note selection, which is much nicer than
the "nothing works in edit mode at all" greedy grab approach used previously.
Attempt #874327892 of getting this damned grabbing right.
Also push the increasingly unwieldly paste parameters into a context object.
As with othe things, currently it is only possible to do "cross-type paste" by
explicitly selecting the target track. We will need to get automation region
view selection working to do better here, but at least for now it's possible to
get the data over.
For some reason, grabbing the magic keyboard focus makes scroll stop working
regardless of what MRV::canvas_group_event() returns. I can't figure out any
reason to grab the keyboard in this case anyway, so I just removed it.
Also simlify MRV event handling code in general.
This lets us get a more explicit handle on time conversions, and is the main
step towards using actual beat:tick time and getting away from floating point
precision problems.
No functional changes in this one (for easier auditing), but towards having
round up/down only if necessary modes, rather than kludging around that
situation with a double round as we do currently.
The idea here is that pasting several times to the same location doesn't make
sense. Instead, the paste is appended past the last paste, snapped to the
grid. This make it simple to replicate a given section a number of times,
simply by copying once and pasting several times.
This behaviour only appears when successive pastes are done to the same
location (whatever the edit point is). When the paste point changes, the
"multi-paste" state is reset.
Boots 'n cats 'n boots 'n cats.
This makes for extremely confusing behaviour, particularly when creating new
regions. This is still probably too transparent, IMO, but at least isn't
totally mysterious. "visible" is a bit of a misnomer in the code, now.
Fixes crash/assert with negative Beats.
TODO discuss alternative:
automatically extend/trim region (if possible) or
accept but hide notes that are out of bounds. That would need
some solution for ghost notes which still can have negative Beats
while dragging.
Problem: mouse-scrolling over a MIDI region in internal edit mode
never released “magic widget focus” (mod keys and global scrolls after
that were ignored). -> added to leave_notify.
Also, the MouseModeChanged signal needs to be emitted when internal edit,
mode changes in order to trigger MidiRegionView::mouse_mode_changed(),
which in turn releases the magic focus while still hovering over a MIDI
region.
Remove Canvas::Layout, use Canvas::Container for the same purpose, move child-rendering into Item::render_children() so that it
could theoretically be used by any derived type.
Delivery of fake motion events to the editor needed the event coordinates to be
in canvas space, as they are with "real" events. Editor and other objects had
many redundant groups from timbyr's work on gnomecanvas to scroll by moving
groups. We don't need this anymore with cairo-canvas (though possibly a
stationay background group for the canvas might be useful again one day as in
the SAE logo. Its implementation would be fairly different though, since we
would have to explicitly move the group on every scroll, since nothing else
ever moves on scroll).
Also tweaks to text item placement, and switch TimeAxisViewItem from
name_pixbuf to name_text, since ArdourCanvas::Text is already "pixbuf optimized".
commit fdbae82077db53add90df7448a06869dac89acc6
Author: Paul Davis <paul@linuxaudiosystems.com>
Date: Wed Mar 27 21:45:28 2013 -0400
mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more.
commit 59343a8283698e02bc0f622313b29e98f449e4c8
Author: Paul Davis <paul@linuxaudiosystems.com>
Date: Wed Mar 27 01:58:53 2013 -0400
initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished
this commit merges many deep changes in ardour's internal architecture,
combined with a total redesign of how MIDI channel filtering works.
data in a track used to flow from JACK port buffers to diskstream's ringbuffers
and was then copied from the ringbuffers into a BufferSet for use during
Route::process_output_buffers(). The butler thread would handle the movement of
data between the ringbuffers and disk.
with this commit, data now flows from JACK port buffers into the BufferSet used
for Route processing, and is copied from the BufferSet into the diskstream's
ringbuffers (the butler thread continues to handle interactions with disk as
usual).
this change allowed a dramatic consolidation of code and simplification of most
aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see
Route::fill_buffers_with_input() which now concisely describes how we move data
from JACK port buffers into the BufferSet for all Route types (including Tracks).
this work was initially motivated by changing MIDI channel filtering so that we
can process capture and playback independently. there is now a very clean
pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the
no-roll case too - a TODO item).
the channel selector for MIDI tracks has been moved out of the track header and
is now accessible via the context menu. more work is likely here, to make it
(more) obvious to the user when filtering is going on.
Completely eliminate static MIDI controller name code.
Reduce dependency on midnam_patch.h (which would have saved me several hours if I did it earlier).
Store controller name numbers as an integer.
Keep controller names in a map keyed by int instead of a list for fast lookup.
More cleanup of MIDI::Name code.
git-svn-id: svn://localhost/ardour2/branches/3.0@13927 d708f5d6-7413-0410-9779-e7cbd77b26cf
... I think. Not sure precisely, conditions were fuzzy, I just tortured my
mouse button until I could reproduce it.
git-svn-id: svn://localhost/ardour2/branches/3.0@13921 d708f5d6-7413-0410-9779-e7cbd77b26cf
This fixes the note name displayed at a given time to be based on the correct program at that time, and not one in the future.
git-svn-id: svn://localhost/ardour2/branches/3.0@13912 d708f5d6-7413-0410-9779-e7cbd77b26cf
Do this via a simple MasterDeviceNames::note_name() function. The same really
needs to be done for program names, this stuff is absolutely brutal to use.
Store note names in a vector indexed by number instead of a list with string
"numbers" for reasonable lookup time.
Make some references const that should be.
git-svn-id: svn://localhost/ardour2/branches/3.0@13908 d708f5d6-7413-0410-9779-e7cbd77b26cf
Give up trying to hide mode selector when it's useless.
Fix display of program names for default mode.
Abstract out (non-crashy) MidiTimeAxisView::get_device_names().
git-svn-id: svn://localhost/ardour2/branches/3.0@13903 d708f5d6-7413-0410-9779-e7cbd77b26cf
We really need some kind of more sophisticated assert macro that can be
switched to non-fatal logging mode for release builds. A log message, which is
often all that would happen, is a lot better than a trainwrecked performance...
git-svn-id: svn://localhost/ardour2/branches/3.0@13892 d708f5d6-7413-0410-9779-e7cbd77b26cf
mode on double-click with a modifier held down;
prevents creation of malformed notes (#4664).
git-svn-id: svn://localhost/ardour2/branches/3.0@12929 d708f5d6-7413-0410-9779-e7cbd77b26cf
selection drag; always emit SelectionCleared() from
clear_selection_except even if this region's selection
hasn't changed, as we still want to clear the selection
in other regions. Part of #4669.
git-svn-id: svn://localhost/ardour2/branches/3.0@12473 d708f5d6-7413-0410-9779-e7cbd77b26cf
note in a region, so that other regions clear their
selections.
git-svn-id: svn://localhost/ardour2/branches/3.0@12472 d708f5d6-7413-0410-9779-e7cbd77b26cf
It's slightly possible that this causes trivial build failures on different
configurations, but otherwise shouldn't cause any problems (i.e. no actual
changes other than include/naming/namespace stuff). I deliberately avoided
removing libardour-config.h since this can mysteriously break things, though a
few of those do seem to be unnecessary.
This commit only targets includes of ardour/*.h. There is also a very large
number of unnecessary includes of stuff in gtk2_ardour; tackling that should
also give a big improvement in build time when things are modified.
git-svn-id: svn://localhost/ardour2/branches/3.0@12420 d708f5d6-7413-0410-9779-e7cbd77b26cf