Mapping Timeline position to Track position
-------------------------------------------

TrackObject/TimelineObject basic properties (hereafter position):
 start
 duration
 in-point
 priority


Use Cases:

 A TimelineObject tracks one or many TrackObject(s).

 When the TimelineObject position is modified we might need
 to cascade those changes to the controlled TrackObject(s) if those
 TrackObject(s) are 'locked' to the TimelineObject.

 If we modify the positions of a TrackObject that TrackObject is
 'locked' to the TimelineObject, we need to ensure all the other
 co-related TrackObject belong to the same TimelineObject are moved in
 the same way.

 A TrackObject can be temporarily 'unlocked' from its TimelineObject,
 so as to move it independently, and then 'locked' back to it. This
 can allow moves, like shifting audio trackobject in relation to the
 video trackobject (to fix sync issues) and then 'lock' them back so
 as to be able to move them as one entity thereafter.

 When adding TimelineOverlay(s) or TimelineEffect(s) on a
 TimelineObject, we need to ensure the TrackObject(s) that those extra
 effects will create can be added with specific priority offsets, in
 such a way that they always end up "on top" of the TimelineObject's
 existing tracked TrackObject(s).

 When a controlled TrackObject is being moved when 'unlocked', we need
 to make sure the duration/height of the TimelineObject is updated
 accordingly. Ex : moving a TrackObject down by one priority should
 increase the TimelineObject "heigh" property by 1.

 A TimelineObject might want to have a tighter control over which
 Track(s) each of the TrackObjects it is controlling are going. This
 is more obvious in the case of timeline with multiple Tracks of the
 same kind, or if a TimelineObject can produce multiple TrackObjects
 of the same media type (ex: file with multiple audio tracks).


Main Problem:

 There needs to be a mapping between the TimelineObject basic
 properties and its controlled TrackObject(s) position.

Design:

 The TimelineObject listen to TrackObject 'notify' signals

 When it sets a property on its trackobjects, it 'ignores' all
 notifications that happen while setting them.

 Setting a property on a TrackObject will see its property changed,
 and then it emits a notify with the modified property.

 TrackObject::locked
  ges_track_object_set_locked()
  ges_track_object_is_locked()

 Mapping {
   GESTrackObject *object;
   gint64 start_offset;
   gint64 duration_offset;
   gint64 inpoint_offset;
   gint32 priority_offset;
   /* Track ??? */
 }

 P : property
 V : value

 TimelineObject set_property(P,V)
   ignore_notifies = TRUE
   parent.P = V
   foreach child in trackobjects:
     if child.is_locked():
        child.set_property(P, parent.P + mapping(child).P_offset)
   ignore_notifies = FALSE

 TimelineObject child 'notify::P' handler:
   if ignore_notifies:
      return
   if not child.is_locked():
     mapping(child).P_offset = timeline.P - child.P
   else:
     TimelineObject.set_property(P, child value + mapping(child).P_offset)

 TrackObject set_property(P, V)
   update the property locally (P = V)
   emit 'notify::P' signal

 TODO : When do we resync the parent values to have minimal offsets ?
