Table of Contents
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?
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.
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.
> 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 around. > 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 trumpet. 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 start. > 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.