Design of the score accessibility system in MuseScore

In this post I’m going to present in detail my idea for the system that is going to provide feedback for the score. Almost all of the following design is already implemented in the score_accessibility branch of my repository.

For this I’ve created three classes:

1. ScoreAccessibility

2. ElementAccessibilityInfo

3. AccessibleScoreView (not implemented yet)

A. Class description

1. ScoreAcessibility

Since there is only one status bar that needs to be updated and only one screen-reader at a time it makes sense that this class will have at most one instance. I chose to use the Singleton pattern instead of static functions because it makes more sense to me to have an object that represents a curent state than static members. Other advantages of using this pattern are the fact that the object can be accessed from any part of the code by calling ScoreAccessibility::instance and that object can be used as a parameter in functions later on if that is the case.

This class agregates the ElemenetAccessibilityInfo class and the AccessibleScoreView class.

This class exposes two methods and one slot:

– updateAccessibility(ElementAccessibilityInfo* e);

this method updates the status bar using the informations received from parameter “e” and when the the AccessibleScoreView will be implemented it will notify the screen-reader that the accessibility informations have changed.

– clearAccessibilityInfo()

for the moment this method only cleans the status bar.

– slot currentInfoChanged()

this slot updates the information of the current ElementAccessibilityInfo (the one that currently ocupies the status bar)

2. ElementAccessibilityInfo

Here there were two options:

i ) add a virtual method to Element class that will return a string with the accessible information

ii) create a new class that takes care of constructing the accessibility information for an Element

I chose the second one for the following reasons (advantages):

R1) (Single responsability principle) I didn’t want to overcrowd the Element hierarchy with methods that compute and update its accessibility information. By going with the second solution, I’m defering this responsability to the ElementAccessbilityInfo class and the Element class gets (idealy) only:

    – one member accInfo (a pointer to it’s ElementAccessibilityInfo object)

    – a virtual method ElementAccessibilityInfo* accessibilityInfo() that instantiates and returns the object

    – a signal that is emited when the internal information changes and the status bar might need to be updated

R2) Reduce the duplicated code. The initial idea was to not have duplicated code at all, the informations would be added using inheritance.

R3) The visual/conceptual way of looking at score elements doesn’t match always 1:1 to how the inheritance hierarchy is implemented for Elemenets. By creating a new class I’m able to create a new hierarchy.

(this example might debatable and I won’t inherit myself also NoteAccessibilityInfo from RestAccessibilityInfo, but it goes to show that, musically, things are a bit different from how they are programmed)

For example: a note can be viewed musically as a rest with a pitch – both have a duration, a measure, a beat, the rest has a reduced set of annotations that can be added to it, where as the note can have annotations, accidentals, articulations, grace notes, etc. If you look at things this way, the note can inherit from the rest class. But every note has a duration only musically, programatically, notes are grouped in chords and the chord has the duration. It makes sense to implement things the way they are now, but it doesn’t make sense to provide info about a note to the user without giving its duration.

R4) Saving memory (not implemented yet completly). It makes sense to me (at least now, maybe things will change as I implement further) that at every point, only one accessibility object/info needs to be instantiated, the one that curently occupies the status bar. At this point, the object that contains all the information is not created until the respective element is not selecte. ( but it is not destroyed once created, at the moment )

R5) At one point I might want to implement feedback for commands (and maybe other things) not just for elements. Then idealy I need a base class and I don’t see any way (conceptually speaking) to connect elements with commands, but I can see a base class AccessibilityInfo that is inherited by ElementAccessibilityInfo and CommandAccessibilityInfo

R6) Self mentaining code – As long as the getters in the interfaces of Element hierarchy classes remain the same, there is no reason to change any code in the ElemenetAccessibilityInfo hierarchy, even if the internal structure changes.

Disadvantages:

D1) R3) unfortunatelly goes both ways, so I can’t always do things as efficient as I want and without duplicating code, or finding a compromise solution.

D2) I might not always have getters for the information that I need

The ElementAccessibilityInfo class has only two public functions and a signal:

QList<QString> info() that returns a list with all the informations as QStrings

updateInfo() which updates the strings in the list returned by info

– (signal) infoChanged() this signal annouces that the strings have changed and you might want to call info() again.

ElementAccessibilityInfo can be see from the point of view of design patterns as a Template, because info calls updateInfo, which is virtual, since every derived class needs to update in its own way.

AccessibleScoreView

This class will inherit QAccessibleWidget (implementing in this way QAccessibleInterface) so that the screen-reader will see the informations that I will provide. By talking to Frederik Gladhorn, one of the main developers for accessibility from Qt, I understood that the idea with the status bar was not enough, because I can’t make the screen-reader tell those informations without giving focus to the status bar. Most screen-readers ignore any changes that happen to widgets that don’t have focus. Since the ScoreView is the widget that has focus when selecting different score elements, I chose to implement this class.

B. Workflow

1) the client (in my case the selectSingle function) calls the Element::accessibilityInfo method

2) the Element::accessibilityInfo method checks if Element has an instance of ElementAccessibilityInfo, or subclass, if not it creates one and it returns it.

3) The ElementAccessibilityInfo class constructs the necesary info in the constructor and connects its infoChanged signal with the parent’s accessibilityInfoChanged signal

4) the client gets the instance of ScoreAccessibility, by calling ScoreAccessibility::instance()

5) the client calls using instance from 4) the ScoreAccessibility::updateAccessibility method using the ElementAccessibilityInfo object that he obtained at 2) as parameter

6) ScoreAccessibility::updateAccessibility looks if the current given parameter is the object that it already had, if not, it dissconects its infoChanged slot from the signal of the former object, it connects the signal to the the new object, and it replaces the former object with the parameter. After that it calls ElementAccesibilityInfo::info and updates the status bar and the screen-reader.

7) Everytime the ElementAccessibilityInfo::infoChanged is emited, the ScoreAccessibility class calls updateAccessbility giving as a parameter the object that it already has.

Other advantage:

– Loose-coupling – as can be seen in the workflow the ScoreAccessibility class has no idea about the Element or ElementAccessibility hierarchy, or about what are those informations that it receives. This is a big plus if as I said earlier I want to implement feedback for commands. The only change that I would need to do is modify everywhere is ElementAccessibilityInfo to AccessibilityInfo (2 places 🙂 )

At first it seems like if I would’ve implemented everything directly in the Element I would’ve not needed the signals, but I would still need a system to tell the ScoreAccessibility that the information has changed and it needs to update itself. At most, the accessibilityInfoChanged signal would be directly connected to the currentInfoChanged slot. This way there is another signal involved, but it is connected and disconected in the constructor, respectively in the destructor of the ElementAccessibilityInfo, so it was taken care of and I see no reason in the future for someone to manually connect these 2 signals in any other way.

One of the reasons I wrote this post is so Marc Sabatella can see my full thinking process behind the code, otherwise it would have probably been included in the tommorow’s weekly update. I’m going to discuss these ideas with him and I will let you know if anything changes. Mostly we are going to talk about the disadvantages that I haven’t seen, because naturaly if I had seen them, I wouldn’t have chosen these solutions. 😀 Of course, if anybody else has a comment, or advice I’m happy to hear them all. 🙂

Advertisements

One thought on “Design of the score accessibility system in MuseScore”

  1. Thanks for the detailed writeup!

    On first read, your advantage R5 (ability to extend the scheme to handle commands rather than just elements) is the strongest argument I see for the choice you made to implement a separate class heirarchy for accessibility info rather than build everything into the element classes.

    I still need to think about it more. My sense is that it will be hard to sell other developers on this scheme, and I fear that it won’t be nearly as self-maintaining as you’d like.

    I would look at score layout as a good example of how MuseScore gets things done. It’s quite procedural, really. Each element has a layout() method to calculate its own position and bounding box, and conceptually at least, the main doLayout() function just loops through the elements asking them to lay themselves out. The reality of course is that doLayout() has lots of code – including big switch statements – that goes way beyond just asking everyone to lay themselves out. It’s actually pretty complex. But the point is, it is all done with just a single layout() function in each element and some procedural code to orchestrate the calling of these. There is no separate hierarchy of ElementLayoutInfo classes, no signals and slots, etc. And score layout is a *much* more complex task than updating a status bar or otherwise providing feedback on the elements.

    As we discussed on IRC, I’d also like to see the Bar/Beat info factored out and displayed in a guaranteed consistent way, although that’s probably doable within your current framework. There could be fields in ElementAcessibilityInfo that are set by each subclass as necessary, and those field read by the main updateAccessibility function and used to populate a sub-area within the status bar.

    Again, your R5 is a good argument for not relying completely on the elements to construct all of their own accessibility info. But I’d still like to explore other options with you when we get a chance. Some other concerns I have are making sure the strings used are all translatable (that’s nit hard) and making sure there is nothing in libmscore/ that relies on things that we only allow in mscore/ (eg, UI-related stuff). Not sure if the signal/slot stuff is a deal breaker, but it might be.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s