Table of Contents
Rosegarden's code overview
I am not myself a RG developer, so any hardcore Rosegardener's comments, additions or corrections to this document will be very welcome. It would be also nice if the doxy output was published somewhere in the web site so it could be referenced from the wiki.
Lately I found myself missing a couple of features in RG, so I figured out I'd scratch my own itch and contribute them to the project.
RG's code is very scarcely commented and not very clearly organized, since it has seen many contributors through many years. Sure, it could really use some cleaning up, refactoring and commenting, but… hey, who wouldn't? That's a lot of hard work waiting for someone with the expertise, the motivation and, above all, the time to tackle it.
Anyhoo, it is difficult for the newcomer to get his bearings quickly. So I gathered around the available documentation, checked out the SVN repo, generated the doxygen output and tried to get the overall picture so I could know where to make the changes I needed.
This meager overview is the result of that research work, I hope it at least saves any new prospective Rosegarden contributor a couple of hours scouring the source tree. Some of the information is copied verbatim from the doxygen main page.
The source tree
RG's source tree organization is a first strong clue on the application structure. (link to the appropiate page of the doxy)
The entry point to the application is in src/gui/application/main.cpp. It basically creates a RosegardenApplication and a RosegardenMainWindow objects.
The base classes
These classes are used to represent internally any Rosegarden project. If you open the contents of a .rg file you will find it is, more or less, a gzipped XML dump of this structure.
This opens up an intriguing possibility. You could use this knowledge to modify a .rg file outside of the Rosegarden application, then load it and see what happens. Useful for batch processing, quick proof-of-concept tests, etc.
This class is used by the GUI class RosegardenMainWindow to manage .rg files. There is only one document object at a time. A RosegardenDocument instance provides access to a Studio and a Composition.
This class encapsulates the idea of a virtual studio. It manages the available Devices (MIDI, audio and DSSI synth plugins), MIDI filters and the metronome.
There are three classes of devices: audio, MIDI and synth.
Devices provide Instruments.
Instrument corresponds broadly to a MIDI or Audio channel, and is the destination for a performed Event. Each Track is mapped to a single Instrument (although many Tracks may have the same Instrument), and the Instrument is indicated in the header at the left of the Track's row in the GUI.
There are three types of instruments, although all three are supported by the same class:
A Buss is basically a mixing console strip. You get to control level, pan and plugins (post-fader inserts?)
Composition is the container for the entire piece of music. It consists of a set of Segments, together with a set of Tracks that the Segments may or may not be associated with, a set of Instruments, and some information about time signature and tempo changes. (The latter are not stored in Segments; they are only stored in the top-level Composition. You can't have differing time signatures or tempos in different Segments.) Any code that wants to know about the locations of bar lines, or request real-time calculations based on tempo changes, talks to the Composition.
Track is much the same thing as on a mixing table, usually assigned to an instrument, a voice, etc. Although a Track is not a container of Events and is not strictly a container of Segments either, it is referred to by a set of Segments that are therefore mutually associated with the same instruments and parameters. In GUI terms, the Track is a horizontal row on the main Rosegarden window, whereas a Segment is a single blue box within that row, of which there may be any number.
Segment is a series of consecutive Events found on the same Track, automatically ordered by their absolute time. It's the usual container for Events. A Segment has a starting time that can be changed, and a duration that is based solely on the end time of the last Event it contains. Note that in order to facilitate musical notation editing, we explicitly store silences as series of rest Events; thus a Segment really should contain no gaps between its Events. (This isn't checked anywhere and nothing will break very badly if there are gaps, but notation won't quite work correctly.)
The class Segment is itself a container, since its parent class is std::multiset<Event*, Event::EventCmp>
Event is the basic musical element. It's more or less a generalization of the MIDI event. Each note or rest, each key change or tempo change, is an event: there's no “note class” or “rest class” as such, they are simply represented by events whose type happens to be “note” or “rest”. Each Event has a type code, absolute time (the moment at which the Event starts, relative only to the start of the Composition) and duration (usually non-zero only for notes and rests), together with an arbitrary set of named and typed properties that can be assigned and queried dynamically by other parts of the application. So, for example, a note event is likely to have an integer property called “pitch”, and probably a “velocity”, as well as potentially many others – but this is not fixed anywhere, and there's no definition of what exactly a note is: client code is simply expected to ignore any unrecognised events or properties and to cope if properties that should be there are not.
The GUI classes
It is assumed that anyone who wants to contribute to Rosegarden has more than a passing familiarity with the Qt toolkit. Otherwise, I suggest you start here http://doc.qt.nokia.com/latest/tutorials.html and come back when you have a good grasp of it.
The main window
This is the main window, containing everything from the application menu to the status bar.
RosegardenMainWindow is the place of creation of many of the widgets that make up the GUI of the application, including many dialogs not visible until the user calls for them.
It also contains references to non-GUI classes, like the current RosegardenDocument or the SequencerThread.
For a brief walkthrough of adding a menu item, see How to Add Menu Items
A widget that arranges a set of Rosegarden parameter-box widgets within a frame, in a dynamically configurable manner.
It is the main widget inside the left QDockWidget. Contains a SegmentParameterBox, a TrackParameterBox and an InstrumentParameterBox.
Its contents apply to the currently selected Segment(s).
Its contents apply to the currently selected Track and depend on which kind of Instrument is associated to it.
Its contents apply to the Instrument associated with the currently selected Track, and depend on the type of instrument it is: MIDI, Audio or Synth.
This widget occupies the right and center area of the main window and is mainly a wrapper around the TrackEditor.
The RosegardenMainViewWidget class provides the view widget for the RosegardenMainWindow instance. The View instance inherits QWidget as a base class and represents the view object of a QMainWindow. As RosegardenMainViewWidget is part of the document-view model, it needs a reference to the document object connected with it by the RosegardenMainWindow class to manipulate and display the document structure provided by the RosegardenDocument class.
Shows a global overview of the composition, and lets the user manipulate the segments.
Contains from left to right and from top to bottom the following widgets:
The Audio classes