Mouseless operation

• Feb 23, 2015 - 19:22

First, I would like to know enough about musescore to be able to implement these request myself, regardless of who actually implements such features; and I would like to know enough to be able to contribute sensibly to the project should it be me who implements it. I want to be better at programming apps like musescore, so it is a good place to learn.

What I would like to know, first and foremost, is the best way to approach plumbing in the features I am about to describe: this is not a request to the programmers of musescore to do it for me, it's just that 164,000 lines of code is more than I can comfortably read or keep in my head at one time. I like things small, and need them that way to work on them. Thus generally my questions will take the form 'how do I plumb this bit of code into musescore', once I have working code for what I wish to plumb in.

Now,

The way I would like musescore to work is to make mouse entirely optional, and keyboard (midi and qwerty) control as straightforward as possible. Vim and Renoise are good examples of how I like things. But the ability not to need to use the mouse pointer is very desirable for me.

I would ideally like the keyboard shortcuts to take the form of a stack of dictionaries (hashmaps) which take a keypress event (Something like 'Alt-X') and turn it into a command 'Turn NoteInput On'. The current shortcuts works a bit like this. But I would like a stack where the lookup goes through the stack top-down, stopping at the first match. Some of the commands would take the form 'Select ShortcutStack Foo' or 'Push ShortcutStack Bar' or 'Pop ShortcutStack'. Something like that. Related is the abilty to say 'Set GuiColour to Red' or to green or any other colour, so that the colour of the controls acts as a clear visual indicator as to what mode I'm in. This last feature is inspired by the way in vim I cannot see what mode it is in, or at least not without difficulty. In my head I can learn that if the controls are red, pressing 'Alt-X' does 'Say Hello' but if the controls are purple, 'Alt-X' does 'Load Template3'. This should be simple to program if I know where and how to connect it into the musescore code.

I am happy to write the code that implements this ShortcutStack. I am happy to write a reference example of the command language, but basically something powerful to do anything that that UI controls can tell the application to do subject to being reasonably trivial to implement in either Python, Javascript or C++ using basic data structures only. I tend to think generally, so I aim to refine the idea into someting short and sweet and generally applicable rather than being a musescore only thing.


Comments

Hello, and thanks for your interest!

In case you aren't aware, making MuseScore usable without a mouse has been a major development thrust in 2.0 and will continue afterwards. This is a crucial accessibility issue - blind users pretty much depend on being able to control things with keybaord rather than mosue. Great strides have been made already in 2.0, but there is plenty of work left to do.

I'm not sure how the "stack" you refer to really fits into that. It seems that an implementation detial that is orthogonal to the goal of making everything keybaord-controllable. But FWIW, we do already have "states" to define when each shortcut is active, and I believe it is sometimes the case that the same shortcut might have different effects in different states (although I am not sure to what extent this is actually supported).

In reply to by Marc Sabatella

Hi,

The sort of answer I am after is along the lines of
When a key is pressed, method X in file A.cpp is called, this normally calls
Y in B.cpp etc.
That way I can easily find where things are in the code. Is there some kind of programmers
roadmap that gives a quick illustration of the flow of events without actually reading the source
itself. I would happily try and put one together and illustrate why I consider such things important.
(I am pedantic about minimising the mental effort of the developer when it comes to programming:
reading C++ is hard compared to a simple diagram that explains what happens when the user
does something -- obviously developers may be more interested in coding features, which is why
I am happy to do this if you can help me know where things are.)

To reiterate, I am interested in hacknig the code to do things I want, both to play with my own ideas, and to target use-cases that may not be a priority for the musescore developers. The ability to do so is core to the power of open source, but learning your way through over 100k lines of code (according to wc -l) is, IMO, best done by asking people who already know their way around the code rather than trying to read it like a novel and remember it all.

The stack idea allows for flexible temporary overrides. For example a mode which adds bindings related to a specific task, but leaves all other bindings as is.

To illustrate what I mean, I wrote a trivial Python interpretation. Basically this means you can have a dictionary of key-action maps, and push them to the top of the stack, and these override what is defined before, and popping restores the previous state. Then colour-coding the UI to indicate modes is the other idea.

Then the idea of having buttons and actions all call code written in a scripting language appeals to me, so that I can have arbitrary behaviour assigned to either keypresses or buttons or menuitems and so on. I am not a great believer in the monolithic application whose design has anticipated the user's every need.

In any case, I am still interested in knowing where in the code to go so as to play around. In time I hope to learn most of it. The question remains: if I wish to hack in my own keyboard handling logic, and no matter how good a programmer and UX designer you are, the user will always know what they want better than you, where in the code do I look.

Related is I'd love to have a pyqt4 component for the actual score bit (minus the toolbars etc) that I can drop into a pyqt application and control with whatever python code I want. Then if I have a use-case that is away from that of the intended audience of musescore, I can mould the code to suit the use-case.

For example, if I wanted to get a window up with just the score view, and none of the musescore UX code present (that is, use the score view, but write my own controller, to use the MVC paradigm), what is the best way to go about adapting the code?

I could, in theory, try to read all the code to learn this, but surely people on this forum already know and can simply point to the relevant bit of code with a few bits of advice as to lessons they've learned from understanding it. This saves time on the part of someone learning the code.

Attached is a Python3 sketch of the basic functionality I have in mind regarding the 'shortcut stack'. This gives a flexible means of turning keypresses into commands, where the commands are then handled by some other part of the code. For example, I could plumb in TinyJS and have every key call a Javascript function, and have every bit of functionality of the program accessible to this scripting core. If this sounds a little like an Emacs for score editing, you have in mind the picture I do, though Lisp is not my favourite language for use cases where Lisp is not strictly necessary.

Attachment Size
ShortcutStack.py_.txt 4.31 KB

In reply to by john.allsup

Unfortunately, there is no place in the MuseScore code where you can see "When a key is pressed, method X is called".

MuseScore is based on Qt and depends on it for a part of the shortcut management. You can find most of the actions that can be invoked by shortcuts in libmscore/shortcuts.cpp. The shortcuts themself, the keystrokes are defined in shortcuts.xml loaded in Shortcut::load().
Shorcuts are linked to QAction which is Qt class. When the keystrokes is pressed, the QAction triggered signal is called. MuseScore connects this signal to the Musescore::cmd() slot, which is the start of the actual "action".

In reply to by john.allsup

Its not necessary to read 100k+ code lines to understand the basics of MuseScore. Fire up a good debugger and set a breakpoint at one of the action routines, say edit.cpp Score::cmdAddPitch(...). Then press run and add a note into a score to trigger the breakpoint. On the stack you see the information from were you come and by setting more breakpoints you can step through the program to get an idea of whats going on during the processing of the command.

I doubt that MuseScore is the right environment to try out new generic concepts as it is huge and complicated but i don't want to discourage you. Good Luck!

Do you still have an unanswered question? Please log in first to post your question.