w3c / mnx

Music Notation CG next-generation music markup proposal.
179 stars 18 forks source link

How to code a system's left-margin labels #277

Open notator opened 2 years ago

notator commented 2 years ago

This proposal

As a reminder of how to code a grand staff, see @clnoel's https://github.com/w3c/mnx/issues/185#issuecomment-974201595 (point 5).

Thoughts about Recursion Simple recursion is possible in XML schemas (See https://stackoverflow.com/questions/148988/recursion-in-an-xml-schema). Edit: Forward declarations _are_ allowed in [XML schema](https://www.w3.org/TR/xmlschema-1/#d0e1610), so the workaround below is probably not necessary: > Forward reference to named definitions and declarations _is_ allowed, both within and between _schema documents_. By the time the component corresponding to an XML representation which contains a forward reference is actually needed for _validation_ an appropriately-named component may have become available to discharge the reference. _If_ the following two-level recursion is a problem ``` ``` we could simply create two new elements (`` and ``), and limit the nesting to two levels: ``` ``` This would only affect Example 4 below. If thought necessary, three levels could also be implemented in this way.

Definitions of Proposed New Elements The code in the rest of this proposal assumes the following new elements: - two low-level helper elements for creating multi-line text blocks. (We've discussed this before, but don't seem to have come to any conclusion. I've adopted this solution here as a temporary measure. These details could be changed later.): - ``: - Attribute `text` (a [String](https://w3c.github.io/mnx/docs/mnx-reference/data-types/string/)): defines a string of text that will be rendered in a single line. - Content: none - ``: - Attibutes: none - Content: one or more `` elements that define the lines of a multi-line text block. - three new grouping symbol elements (bracket types): The use of "symbol" in these names is consistent with current usage in the docs (and MusicXML), but I think its confusing. I'd rather call these ``, `` and ``. - ``: - Attributes `type`, `top-staff` and `bottom-staff`. - Content: a mixed list of one or more `` and/or `` elements N.B. two-level recursion: `` contains ``. - ``: - Attributes `type`, `top-staff` and `bottom-staff`. - Content: an optional `` element that will be rendered to its immediate left. - ``: - Attributes: `type`, `top-staff` and `bottom-staff`. - Content: none The `type` attributes take [grouping symbol](https://w3c.github.io/mnx/docs/mnx-reference/data-types/grouping-symbol/) values. The `top-staff` and `bottom-staff` attributes are staff indices in the ``. The top staff has index 1 and the index increments downwards. Staves inside `` elements count individually. - two new label elements - `` - Attributes: - `column-align` -- optional attribute having possible values `left|center|right`. Default: `center` Aligns this `` with respect to the widest `` in the same column in the system label. The right edges of `` and `` elements in the same column are always aligned. - Content: - a `` element - a `` or `` element. The `` is positioned to the left of, and is vertically aligned with the vertical centre of, the contained ``. - `` - Attributes: - `staff` -- the staff index in the system. - `column-align` -- optional attribute having possible values `left|center|right`. Default: `center` Aligns this `` with respect to the widest `` in the same column in the system label. The right edges of `` elements in the same column are always aligned. - Content: - a `` element. - an optional `` element. The `` is aligned horizontally with the staff, and immediately to the left of it, separated from the staff only by any `` or `` element that includes the staff.

Coded example diagrams

Example 1: 4hornsPiano These are coded in two separate <system-layout>s: "page1SystemLayout" and "defaultSystemLayout". (In this case, the only difference between the two <system-layout>s is in the outer <string> associated with the upper <group-label>. I think its better to assume that the two layouts might be very different, and not to attempt any optimisation at this point.)

Code ``` // one staff (one voice, could be two note chords on one stem) // the part must be homophonic // the part must be homophonic // one staff (one voice, could be two note chords on one stem) // the part must be homophonic // the part must be homophonic. // two staves // the part must contain staves (be polyphonic) // staff 1 in system // staff 2 in system // staves 3 and 4 in system //**************************** // page1SystemLayout // replaced by "Hn." in the defaultSystemLayout below //**************************** // staff 1 in system // staff 2 in system // staves 3 and 4 in system //**************************** // defaultSystemLayout // replaces "4 Horns in F" in the page1SystemLayout //**************************** ```

Example 2: TwoVoices Two Voices on a staff: The <staff-label> on staff 1 uses a multi-line <text-block>. Multi-line <text-block>s can also be used in <group-label>s.

Code ``` // one staff (two voices, could be two note chords on each stem) // the part must be homophonic // the part must be homophonic // the part must be homophonic // the part must be homophonic // two staves // the part must contain staves (be polyphonic) // staff 1 in system // staves 2 and 3 in system // Could also contain a ```

Example 3: bracket ordering This is the brackets ordering issue posed in #276. I've put the answer here because it needs to be part of the general solution.

Code ``` // one staff (one voice) // the part must be homophonic // one staff (one voice) // the part must be homophonic // one staff (one voice) // the part must be homophonic // staff 1 in system // staff 2 in system // staff 3 in system //********************** // layoutA //********************** // staff 1 in system // staff 2 in system // staff 3 in system //********************** // layoutB //********************** ```

Example 4: groupGroup A score for two groups of players, one on the left of the stage, one on the right. Demonstrates <group-label> nesting.

Code ``` // one staff (one voice) // the part must be homophonic // two staves // the part must contain staves (be polyphonic) // one staff (one voice) // the part must be homophonic // two staves // the part must contain staves (be polyphonic) // staff 1 in system // staves 2 and 3 in system // staff 4 in system // staves 5 and 6 in system // end of top large bracket // end of bottom large bracket ```
notator commented 2 years ago

I've now edited the above proposal, adding optional column-align attributes to <group-label> and <staff-label>. column-align can take values left|center|right, and has default center. All the examples except Example 3 use column-align="center". Example 3 uses <staff-label ... column-align="right"/>

clnoel commented 2 years ago

I have to say I dislike this proposal, with the notable exception of the text-block element, which is actually #278. We already have a grouping hierarchy, and it feels like a step backwards. I want to handle the symbols and layouts inside the -layouts hierarchy, not separately. However, the counter proposal I have thus far come up with does not handle Example 4 properly, so I'm still thinking.

notator commented 2 years ago

I want to handle the symbols and layouts inside the -layouts hierarchy, not separately.

I don't think that can work. The same part may have to be labelled differently in different system layouts. The left-margin labels actually apply to staves, not parts.

clnoel commented 2 years ago

@notator Yes, we have to apply labels to staff-layouts & group-layouts, not to part-layouts. That doesn't mean it can't happen in the layout-hierarchy.

Okay, so let's say that default positioning of brackets have them going from children on the right to parents on the left. And default positioning of labels has them to the left of all brackets, once again where children-to-parents = right-to-left. Labels are vertically centered on their staff or on their group symbol.

Surveying a random sampling of real chamber music and orchestral scores on imslp.org showed this being by far the most common configuration.

Please note that while I have tried to come up with good names, I am not tied to them. For instance label-source below could be part-source, part-ref, part-id, etc. I've been through all of those options when making these examples, and I finally just picked one.

Proposal

For this purpose, then, I'd like to propose a child to both group-layout and staff-layout: <label> Contents: The contents of <label> will take on whatever format we decide is best in the text-block discussion in #278, which is beside the point for this discussion, so I'll use the <string> children like you did in your proposal. Attributes: label-source: The value is a part id. When defined, instead of the contents of <label> use the name or short-name of the referenced part. The contents of <label> should be empty if this is defined. label-type: enum with values short and long (default long) only has meaning if label-source is also defined, and determines whether the name (long) or short-name (short) of the part is used for this label.

I would like to add the new attribute symbol-placement to <group-layout> symbol-placement: enum with values leftmost, rightmost, inside-parent, and outside-parent, defaults to inside-parent. This changes the placement of the group's symbol relative to the rest of the stack of symbols.

I would like to add the new attribute label-placement to both <group-layout> and <staff-layout> label-placement: enum with values over-staff, leftmost, rightmost, inside-symbol, outside-symbol, inside-label-parent outside-label-parent, and aligned-label-parent, defaults to leftmost. This changes the location of the label relative to the other labels and symbols in the hierarchy. The containing symbol for a label on a group-layout is that group's symbol. The containing symbol for a label on a staff-layout is the symbol of the containing group (if any). The parent label is the label of next highest-group in the hierarchy.

Note: In the examples below, I have removed the idea of reusable -layout elements (except system-layout), which are not part of the current spec, partially because most people did not want to try track that. It makes for longer files, but actually removes quite a bit of complexity, since you don't have to worry about how the individual elements might be reused in different system-layouts.

Example 1&2

Code ``` ... ... ... ... ... ... ... ```

Example 3

This actually becomes dead simple. The first one is the default positioning, and the second requires only one additional symbol-placement tag.

Code ``` ... ... ... ... ... ... ```

Example 4

The one problem I have with my proposal is that there is more than one way to do things. Both of the following work for this example.

Code 1 (Inside/Outside) ``` ... ... ... ... ... ... ```
Code 2 (Rightmost) ``` ... ... ... ... ... ... ```

Alternate Proposal:

It might be that the placement enums are too complicated (or cumbersome) for programs (rather than humans) to properly assign in a way that conforms to "one way to do things". In that case, we would instead define "columns". These columns are referenced right-to-left across vertical placements for both symbols and labels. Anything that lines up vertically is given the same column number, and the symbol-placement and label-placement attributes become the integer attributes symbol-column and label-column.