Exploring code and data structures

Updated 10 months ago

How to get started

After you have downloaded a Nightly Build or made you own version, you are ready to explore data structures and code. In a score right click on a note or any other item and select "Object Debugger" from the right-click menu. This will give you an opportunity to explore the data structures. Also, there is "Edit → Debugger", that lets you explore the data in a score. Note: that debugger nowadays is only enabled when running MuseScore in 'experimental' mode, i.e. using the -e option, see also Command line options

Getting started in the source tree

MuseScore's main() function is in main/main.cpp. As with any C or C++ application, the main() function is the first thing that runs when the program is started. In MuseScore's case, the main() function hands over to another function called runApplication() in mscore/musescore.cpp. This function sets up the QApplication and then calls qApp->exec() to launch the Event Loop.

The Event Loop continuously checks for events, including user input events such as mouse clicks and button presses, and then passes execution to the relevant event handler (e.g. QWidget::keyPressEvent()). Event handlers are just ordinary C++ member functions that happen to get called when an event happens. Event handlers can be installed on any widget (buttons, menus, dialogs, windows, etc.) and can be used to create or destroy other widgets as well as ordinary C++ objects. This is how execution is passed around the program.

Most of the important code lives in the mscore and libmscore directories. The MuseScore class and its functions are declared in the header file mscore/musescore.h and defined in the companion source file mscore/musescore.cpp.

Note: The MuseScore class is a subclass of QMainWindow, so in addition to its own functions (those declared in mscore/musescore.h and defined in the corresponding .cpp file), it has also access to all of the functions that belong to QMainWindow and its ancestor classes all the way back to QWidget, and eventually QObject.

Commands are processed in MuseScore::cmd(). Most commands that modify the score are passed off to ScoreView::cmd in scoreview.cpp. If you put a breakpoint in ScoreView::cmd, you can find and then step into the function that processes a specific command. Commands like cut, copy, paste are posted as a new event right at the start of ScoreView::cmd. These events are then processed in ScoreView::normalCut, ScoreView::normalCopy, ScoreView::normalPaste. The paste execution ends up in mscore/libmscore/cmd.cpp Score::cmdPaste. Note that copy and paste put content onto the clipboard through the interface provided by Qt (in ScoreView::normalCopy()). Quite a few commands, like changing the duration of a note, are handled right at the end of this function where _score->cmd() is called. In mscore/libmscore you find the source for the various classes and the layout algorithm. If you sort the directory by file size, you'll easily spot where most processing is done: measure.cpp, score.cpp, cmd.cpp, undo.cpp., layout.cpp. edit.cpp and chord.cpp.