Linked Segments

What is it?

The ability to have segments linked together. In its simplest form, linked segments would appear identical - the events in one would appear to be the same as the events in the others to which it was linked. Edits to a linked segment would be reflected in its siblings.

It's been discussed to be able to have relative transpositions or time stretches or squashes on the linked segments. It remains to be seen whether these will be implementable in practice.

Why implement it?

  • Various users have asked for it on the tracker
  • It would be very useful for drums or electronica, or in any genre with a high degree of repetition
  • In classical work it might be useful where various different instruments play the same sequence
  • It has potential to be used to be able to view repeating segments in the notation editor (Yves is working on this)

The current mechanism for coordinating segment content is basically copy-pasting. Anything which could automate this is hopefully a good thing!

How do I try it?

There's a branch called linked_segments_ian which has the beginnings of a working implementation of this. It will be merged on to the trunk eventually but this is where it is for the time being.

  • Compile branch and run
  • Make segment, put some notes in
  • Switch to the Select/Edit tool (F2)
  • Control-Alt-left-click-drag the segment to create a link copy. Think of the Alt as a modifier on the existing Control-left-click-drag to create a non-linked copy
  • Open both segments in notation and/or matrix, edit and see the other edit itself accordingly

How's it done?

Segment coordination is handled by the SegmentLinker class. Segments have a SegmentLinker pointer. If this pointer points to a valid SegmentLinker object then it is linked. If this pointer is null then it is just an ordinary segment. Segments which are linked together point to the same SegmentLinker.

All SegmentLinkers are connected to the updateLinkedSegments signal which is emitted from CommandHistory after any command is performed. Recieving this signal is the trigger for doing the segment coordination. SegmentLinker uses the refresh status mechanism to determine whether any of its segments have changed, and if so, refreshes all of its other segments from the changed one.

Each linked segment can have a transposition on it and Events are transposed accordingly when they're coordinated between segments. The same is true for keys. A special attribute can be applied to Events to get it to be ignored by the segment linkage mechanism (if you want to put a non-linking clef change in a segment for example).

The serialisation of linked segments is handled by simply having some extra attributes serialised with the segment - a linker id and some transposition parameters. There is no need to serialise anything from the SegmentLinker class. There should be no problems with forward or backward compatibility between versions with and without linked segment functionality. The worst that will happen is that people loading compositions containing linked segments in older versions which don't support linked segments will just see their linked segments appearing as ordinary segments.


To do:

Initial Implementation:

  • Ui enhancements
    • Make an “unlink” command for linked segments, and some way of firing it
  • Checks
    • check changes of segment copy ctor to clone function, whether they need to be deep or shallow copies (i.e. including the link or not). Need to do something to restrict link-copying to midi segments only
    • check cut/copy/paste of linked segments on the composition canvas is behaving sensibly
  • Bugs
    • resizing of linked segments, particularly from the left, has variable effects
    • cut/copy/paste range with linked segments goes hilariously wrong at the moment if you try it
  • Apply a colour scheme for linked segment groups
  • Repeating Segments
    • Yves has ported his work from the repeats_and_linked_segments to the linked_segments_ian branch, but there may be some more work on this to come

Future work:

  • Ui enhancements
    • Provide a “Paste as link” type menu and keyboard option. Control-Alt-V could paste as links, as a compliment to Control-V pasting as deep copies currently
  • Wishlist
    • have some kind of “advanced paste” dialog to do things like paste a specifiable number of segments line astern at an adjustable start time, and control whether they go down as copies or links
  • Transposition
    • Here's an email discussion from Michael from the dev list which I need to sift through and form a “to do” list out of. I also need to write down a few canonical use-cases for segment transposition, and make sure these are honoured in the final implementation.
> I've put some buttons in a "Linked segments parameters" collapse container
> under the segment panel on the left hand side - one to bring up a
> transpose dialog on a linked segment, and another to reset the transpose
> on a transposed linked segment.

I couldn't figure out how to make it work for my test problem.  Some people 
may think that way, but I don't, so we need some other options here for how to 
specify by what amount to transpose.  Some of the options in this stock  
transpose by interval dialog are going to need adjusting for this use too, I 
think, but I'm not sure exactly how until I have more experience fooling 

> There's also a menu item in the notation editor to add a clef change which
> only applies to one particular linked segment.

It works, and it seems like a good idea.  I don't like how hard this is to 
discover, and if I want to change the existing clef it's not clear how.  I'll 
have to think about that stuff.

> 2. press the "Change" button on the linked segment parameters collapse
> control on the left hand side, choose whatever transposition parameters
> you want. You can change key or not, according to your whim.

Just thinking out loud about a better GUI, not writing a prescription for what 
you're expected to code...

The UI I'm expecting to see out of Rosegarden would have the segment's 
transposition displayed in this special parameter area, so you can see where 
you are at a glance.

I'm thinking that instead of having the parameters in a collapsing frame, what 
we probably want to do is make the SPB smarter and have it display only 
editable properties on linked segments.  The controls in the collapsing frame 
are useless for normal segments, and vice versa.

This could probably work pretty well, I'm thinking "at a glance."  It should 
be pretty straightforward to display only certain properties for linked 
segments, and make those behave differently.  ie. the transpose box shows you 
the transpose of the link, no the master, and manipulating that transpose 
works on the link only, and so on like that.

Where this gets muddy is what to do when there are both linked and standard 
segments in the same selection.  In practice, it might not be all that bad 
though.  There are already a lot of cases where we display a * because 
segments in the current selection have conflicting parameters.  Probably the 
single hardest thing here is that you can edit those *'ed parameters in order 
to change all segments at once.  What happens if you have a selection that 
includes both straight and linked segments that are related to each other, and 
they have a different transpose?  You could get a race condition, or some 
other kind of utter chaos.

> 3. move/add some notes, they should be linked but appear on the stave in
> the correctly offset positions, and if you've chosen to change key also,
> this should be respected.

The key bit is going to need some more thought, so let's do some of that too.

My gut is telling me that while Rosegarden is the application of options and 
has resisted the idea of removing functionality for the sake of simplifying 
things, we have been trending toward reduced simplicity in new features.

It seems the best approach to this business of keys is not to ask, not to 
provide special options, but to just handle it automatically so that the 
transposed links are in the same key as the original.  Key signatures need 
transposed, even clefs need adapted (to be replaced with those special only-
in-the-linked-segment clefs) and that kind of stuff should just happen, 
instead of being presented as options that can be turned off.

Not only will that make Rosegarden easier to use, it will make it easier to 
test too.  When you start allowing n degrees of freedom in all this, it gets 
to be a mind twister trying to figure out if the results even match 
expectations, and whether something is broken or working.

Toward that end, what I'd like to concentrate on first is setting this change 
by interval dialog aside, and using the engine behind the "convert notation 
for" function to direct all of this.  Instead of saying you want to transpose 
by a perfect ninth, you say you want to transpose between a flute and a Bb 

Real music guys know all the interval stuff, which is why one of them wrote 
that transpose by interval dialog, but I always use the "convert notation for" 
thing in my own life.  It's easy, and it works well.  It's a good place to 

> I'm operating at the misty outer limits of my understanding of musical
> notation here, but I *think* I've done the right thing!

My understanding of how to transpose by interval is too bad to really 
appreciate whether I accomplished what I meant to or not, but at least it all 
came out sounding the same way on the far side.  That's the acid test when 
you're faffing about with transposition for notation purposes. If the parts no 
longer sound in unison, then something got screwed up.

The case of taking a flute part to the tuba is an interesting one.

All the stuff we have up to date would preserve exactly the same sound.  I 
take a flute part in a high register and "convert notation for" to turn it 
into a tuba part, and it comes out way the hell above the staff.  When you're 
working on copies, it's reasonable to leave the user to just drop the copy a 
few octaves, but with this link business I'm thinking we need to either:

a) Try to transpose the part into a suitable register automatically (fine idea 
in theory; in practice there would be no recourse if we got off by one octave, 
which seems pretty likely to happen in edge cases)

b) Provide a "local transpose" for the linked segment, the way you have local 
clefs.  This seems like the best approach in some ways, but a complete 
nightmare of an interface, and a mine field for confusion.

Then again, there's always:

c) If the user is moving a part that far between instruments, he's going to 
have to suck it up and make hard copies of the parts, because we're too dumb 
to offer anything more sensible with a reasonable change of getting it right 
with sufficient frequency not to be frustrating.

So again, I'm just brain-storming here, but my gut says a combination of a) 
and c) sounds about right.  Try to do automatic register adjustment so the 
tuba part will sound in a suitable octave, and if we bungle it, just leave the 
user to make hard copies and fix it manually in those edge cases.  The code 
for what I'm thinking of is what would be invoked when adding a clef change 
and "transpose to suitable octave" or whatever.  It works most of the time, 
but occasionally misses the target by one octave.

When I think about it all even more deeply, there's only so much we can do 
automatically on a good day.  What is easy on a flute is not necessarily even 
playable on a tuba, even after adjusting it down a few octaves.  There will 
always be a lot of need for hard copies and manual editing in those cases 
where instruments are that far apart.

> As my implementation stands, there's no facility for editing the transpose
> on a linked segment. You can set the transpose on an untransposed segment,
> or remove the transpose on a transposed one. This is because I don't know
> how to handle a composite transpose. i.e. if a transposition is
> represented by m1 semitones and n1 steps, and we apply another transpose
> of m2 semitones and n2 steps, is it true that the composite transposition
> is always represented by (m1+m2) semitones and (n1+n2) steps? If so, maybe
> it's not much work to implement an edit function for the transposition on
> a linked segment.

Yeah, that sounds like b) above, and I don't know how to handle it either 
without causing my brain to start sizzling inside my skull.

> The code also makes the (possibly false) assumption that if a transposition
> is characterised by m semitones and n steps, then the inverse
> transposition is always characterised by -m semitones and -n steps. Is
> this a safe assumption? It's what I apply to key change events when going
> from a transposed linked segment to the underlying reference segment.

Yes, everything has to balance out evenly so if you +5 here you -5 there.  I 
worked out code for transposing the key signature somewhere in the whole 
process of working on that "convert notation for" stuff, so there's an 
established working example in our code somewhere.

The "convert notation for" stuff I keep referring to is actually in two or 
three different places.  In Track Parameters, you can use the database to pre-
select properties for segments that have not yet been created, and you can 
also use it to transform segments that are already sitting there.  In the 
notation editor, you can "convert notation for" to change what you're sitting 
on top of out from under you.  It's all the same mechanism at the core, with 
the gigantic, massively comprehensive database of instrument properties 
provided by E. Magnus Johannson; essentially we have a good chunk of an 
encyclopedia of arranging built right into Rosegarden.
dev/linked_segments.txt · Last modified: 2022/05/06 16:07 (external edit)
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki