Both of these are currently needed: idle_resize() is required for
::set_height() to take effect on all affected tracks, and
::redisplay_track_views() is needed to reposition all other tracks as
necessary.
This may be incorrect, since track height changes may be driven
directly (e.g. via menu items) rather than by mouse drags. This may
need revisiting and there may need to be a way to separate dragged height
changes from others.
This allows it to be used in an idle callback. If we use
::redisplay_track_views() directly, we do not disconnect the idle
connection. This will happen automatically since the callback will return
false, but it seems better to explicit about this. Even better would be to use
::connect_once() but this may not be available in the version of glibmm that we
are using at present.
It appears that GDK/glib will not run idle callbacks with a lower priority than
HIGH_IDLE+10 *if* a new user input event is pending. This means that if mouse
motion events are arriving and causing resizes of selected tracks, the call
to ::redisplay_track_views() which is needed to update all the other tracks,
will not take place if a new motion event arrives. Changing the priority to
same as is used for the ::idle_resize() callback prevents new motion events
from being handled before ::redisplay_track_views() is called.
::model_changed() is used when the model has changed (eg. new notes or some
notes deleted); ::view_changed() is used when only some view parameter (e.g.
zoom, scroll, track height etc) has been altered.
Not fully functional yet (::view_chanted() ignores scroll)
This allows two reader threads to proceed without blocking each other, as can
happen when the butler renders a MIDI track into an RT-safe buffer while the
GUI reads the same MidiModel/Source for visual display.
This also requires a change in the type of reference held by
a MidiAutomationListBinder.
Both the MidiSource and MidiModel have a reference to each other, and it is
important that we avoid circular references to avoid problems with object
destruction. We had been accomplishing this by having the Model hold a
weak_ptr<MidiSource>. However, the lifetime of a MidiSource and its MidiModel
are coincident and there's really no need to use a smart ptr at all. A normal
reference is just fine. However, due to constructors that accept a serialized
state, we cannot use an actual reference (we cannot set the constructor in the
initializer list), so we use a bare ptr instead.
This forces a similar change in MidiAutomationListBinder, which also maintains
a reference to the Source. However, the only purpose of this object is to
ensure that if the Source is destroyed, relevant commands will be removed from
the undo/redo history, and so all that matters here is that the binder connects
to the Destroyed signal of the source, and arranges for its own destruction
when received.
Note that the previous construction of the binder, actually holding a
shared_ptr<MidiSource> would appear have prevented the Destroyed signal from
ever being emitted (from ~Destructible), and so this may also be a bug fix that
allows MidiSources to actually be deleted (the memory object, not the file).
This also requires a change in the type of reference held by
a MidiAutomationListBinder.
Both the MidiSource and MidiModel have a reference to each other, and it is
important that we avoid circular references to avoid problems with object
destruction. We had been accomplishing this by having the Model hold a
weak_ptr<MidiSource>. However, the lifetime of a MidiSource and its MidiModel
are coincident and there's really no need to use a smart ptr at all. A normal
reference is just fine. However, due to constructors that accept a serialized
state, we cannot use an actual reference (we cannot set the constructor in the
initializer list), so we use a bare ptr instead.
This forces a similar change in MidiAutomationListBinder, which also maintains
a reference to the Source. However, the only purpose of this object is to
ensure that if the Source is destroyed, relevant commands will be removed from
the undo/redo history, and so all that matters here is that the binder connects
to the Destroyed signal of the source, and arranges for its own destruction
when received.
Note that the previous construction of the binder, actually holding a
shared_ptr<MidiSource> would appear have prevented the Destroyed signal from
ever being emitted (from ~Destructible), and so this may also be a bug fix that
allows MidiSources to actually be deleted (the memory object, not the file).