Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Next revision Both sides next revision
dev:overall_code_structure [2008/05/01 11:14]
127.0.0.1 external edit
dev:overall_code_structure [2011/01/19 23:02]
lgarrido
Line 1: Line 1:
-Rosegarden is split into 3 main parts:+====== Rosegarden's code overview ======
  
 +DISCLAIMER:
  
 +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.
  
-===Base===+I found myself missing a couple of small features in RG, so I figured out I'd scratch my own itch and contibute 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. So let's not hold our breaths.
  
 +Anywho, 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.
  
-The base library holds all of the fundamental "music handling" structures, of which the primary ones are EventSegment, Track, Instrument and Composition. It also contains selection of utility and helper classes of a kind that is not specific to any particular GUIEverything here is part of the Rosegarden namespace, and there are no dependencies on KDE or Qt (although it uses the STL heavily).+This meagre overview is the result of that research workI hope it at least saves any new prospective Rosegarden contributor couple of hours scouring the source treeSome of the information is copied verbatim from the doxygen main page.
  
-The keyword for the basic structures in use is "flexibility". Our Event objects can be extended arbitrarily for the convenience of GUI or performance code without having to change their declaration or modify anything in the base library. And most of our assumptions about the use of the container classes can be violated without disastrous side-effects.+===== 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)
  
 +===== main() =====
  
-===Music Structures===+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 =====
  
 +{{:dev:datamodel.png}}
  
-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 applicationSofor 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.+These classes are used to represent internally any Rosegarden projectIf you open the contents of .rg file you will find it ismore 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.
  
 +==== RosegardenDocument ====
  
-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.)+Directory: src/document
  
 +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.
  
 +==== Studio Classes ====
  
-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.+=== Studio ===
  
 +Directory: src/base
  
 +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.
  
-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.+=== Device ===
  
 +Directory: src/base
  
 +There are three classes of devices: audio, MIDI and synth.
  
-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.+  * Audio: at this moment the GUI provides access to one single Audio device with a fixed number of 16 audio outputs (Instruments), a maximum of 16 stereo inputs and a maximum of 8 submasters.
  
-See also docs/data_struct/units.txt for an explanation of the units we use for time and pitch values. See docs/discussion/names.txt for some name-related discussion. See docs/code/creating_events.txt for an explanation of how to create new Events and add properties to them.+  * Synth: there is also one single Synth device that offers the possibility of using up to 24 DSSI plugins (Instruments).
  
 +  * MIDI: MIDI device configuration is more powerful and flexible, probably due to RG's origins as pure MIDI Sequencer. You can add and remove 16-channel MIDI devices at will and connect them to any other alsa-seq device in your system.
  
 +Devices provide Instruments.
  
-The base directory also contains various music-related helper classes:+=== Instrument ===
  
 +Directory: src/base
  
 +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:
  
 +  * Audio: an audio Instrument is an audio mono/stereo channel. Accepts audio from a track and delivers audio to a submaster or to the master.
  
-The NotationTypes.[Ch] files contain classes that help with creating and manipulating events. It's very important to realise that these classes are not the events themselvesalthough there is a Note class in this file, and TimeSignature class, and Clef and Key classes, instances of these are rarely stored anywhere. Instead they're created on-the-fly in order to do calculation related to note durations or time signatures or whatever, and they contain getAsEvent() methods that may be used when an event for storage is required. But the class of a stored event is always simply Event.+  * Syntha synth Instrument is a DSSI software synthesizer. Accepts MIDI events from track and delivers audio to a submaster or to the master.
  
-The NotationTypes classes also define important constants for the names of common properties in Events. For example, the Note class contains Note::EventType, which is the type of note Event, and Note::EventRestType, the type of rest Event; and Key contains Key::EventTypethe type of a key change EventKeyPropertyNamethe name of the property that defines the key changeand a set of the valid strings for key changes.+  * MIDIa MIDI Instrument is a MIDI channel Accepts MIDI events from track and delivers them to another MIDI device. You can control MIDI parameters like BankProgramVolumePanChorus or Reverb.
  
 +=== Buss ===
  
 +Directory: src/base
  
 +A Buss is basically a mixing console strip. You get to control level, pan and plugins (post-fader inserts?)
  
 +==== Composition Classes =====
  
-BaseProperties.[Ch] contains a set of "standard"-ish Event property names that are not basic enough to go in NotationTypes.+=== Composition ===
  
 +Directory: src/base
  
 +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.
  
-SegmentNotationHelper and SegmentPerformanceHelper do tasks that may be useful to notation-type code and performer code respectively. For example, SegmentNotationHelper is used to manage rests when inserting and deleting notes in a score editor, and to create beamed groups and suchlike; SegmentPerformanceHelper generally does calculations involving real performance time of notes (taking into account tied notes, tuplets and tempo changes). These two lightweight helper classes are also usually constructed on-the-fly for use on the events in a given Segment and then discarded after use.+=== Track ===
  
 +Directory: src/base
  
 +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.
  
-Quantizer is used to quantize event timings and set quantized timing properties on those events. Note that quantization is non-destructive, as it takes advantage of the ability to set new Event properties to simply assign the quantized values as separate properties from the original absolute time and duration.+=== Segment ===
  
-GUI+Directory: src/base
  
 +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>
  
-The GUI directory builds into a KDE/Qt application. Like most KDE applications, it follows a document/view model. The document (class RosegardenGUIDoc, which wraps a Composition) can have several views (class RosegardenGUIView), although at the moment only a single one is used. +=== Event ===
- +
-This view is the TrackEditor, which shows all the Composition's Segments organized in Tracks. Each Segment can be edited in two ways: notation (score) or matrix (piano roll). +
- +
- +
- +
-All editor views are derived from EditView. An EditView is the class dealing with the edition per se of the events. It uses several components: +
- +
- +
- +
- +
- +
-  * Layout classes, horizontal and vertical: these are the classes which determine the x and y coordinates of the graphic items representing the events (notes or piano-roll rectangles). They are derived from the LayoutEngine base-class in the base library. +
- +
- +
- +
-  * Tools, which implement each editing function at the GUI (such as insert, erase, cut and paste). These are the tools which appear on the EditView's toolbar. +
- +
- +
- +
-  * Toolbox, which is a simple string => tool map. +
- +
- +
- +
-  * Commands, which are the fundamental implementations of editing operations (both menu functions and tool operations) subclassed from KDE's Command and used for undo and redo. +
- +
- +
- +
-  * a canvas view. Although this isn't a part of the EditView's definition, both of the existing edit views (notation and matrix) use one, because they both use a QCanvas to represent data. +
- +
- +
- +
-  * LinedStaff, a staff with lines. Like the canvas view, this isn't part of the EditView definition, but both views use one. +
- +
-There are currently two editor views: +
- +
- +
- +
-  * NotationView, with accompanying classes NotationHLayout, NotationVLayout, NotationStaff, and all the classes in the notationtool and notationcommands files. These are also closely associated with the NotePixmapFactory and NoteFont classes, which are used to generate notes from component pixmap files. +
- +
- +
- +
-  * MatrixView, with accompanying classes MatrixHLayout, MatrixVLayout, MatrixStaff and other classes in the matrixview files. +
- +
- +
- +
- +
- +
-The editing process works as follows: +
- +
- +
- +
-[NOTE : in the following, we're talking both about events as UI events or user events (mouse button clicks, mouse move, keystrokes, etc...) and Events (our basic music element). To help lift the ambiguity, "events" is for UI events, Events is for Event.] +
  
 +Directory: src/base
  
 +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 =====
  
-The canvas view gets the user events (see NotationCanvasView::contentsMousePressEvent(QMouseEvent*) for an example)It locates where the event occured in terms of musical elementwhich note or staff line the user clicked on, which pitch and time this corresponds to, that kind of stuff(In the Notation and Matrix views, the LinedStaff calculates mappings between coordinates and staff lines: the former is especially complicated because of its support for page layout.)+It is assumed that anyone who wants to contribute to Rosegarden has more than a passing familiarity with the Qt toolkitOtherwise, I suggest you start here http://doc.qt.nokia.com/latest/tutorials.html and come back in a couple of weeks.
  
-The canvas view transmits this kind of info as a signal, which is connected to a slot in the parent EditView.+==== The main window ====
  
-The EditView delegates action to the current tool.+{{:doc:rg-tracks.png}}
  
-The tool performs the actual job (inserting or deleting a note, etc...).+=== RosegardenMainWindow ===
  
-Since this action is usually complex (merely inserting a note requires dealing with the surrounding Events, rests or notes), it does it through a SegmentHelper (for instance, base/SegmentNotationHelper) which "wraps" the complexity into simple calls and performs all the hidden tasks.+Directory: src/gui/application
  
 +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.
  
-The EditView also maintains (obviously) its visual appearance with the layout classes, applying them when appropriate.+It also contains references to non-GUI classes, like the current RosegardenDocument or the SequencerThread.
  
 +== RosegardenParameterArea ==
  
 +Directory: src/gui/editors/parameters
  
-===Sequencer===+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.
  
 +== SegmentParameterBox ==
  
-The sequencer directory also builds into a KDE/Qt application, but one which doesn't have a gui. The Sequencer can be started automatically by the main Rosegarden GUI or manually if testing - it's sometimes more convenient to do the latter as the Sequencer needs to be connected up to the underlying sound system every time it is started.+Directory: src/gui/editors/parameters
  
-The Sequencer interfaces directly with ALSA and provides MIDI "play" and "record" ports which can be connected to other MIDI clients (MIDI IN and OUT hardware ports or ALSA synth devicesusing any ALSA MIDI Connection ManagerThe Sequencer also supports playing and recording of Audio sample files using Jack+Its contents apply to the currently selected Segment(s).
  
 +== TrackParameterBox ==
  
 +Directory: src/gui/editors/parameters
  
-The GUI and Sequencer communicate using the KDE DCOP communication frameworkLook in:+Its contents apply to the currently selected Track and depend on which kind of Instrument is associated to it.
  
 +== InstrumentParameterBox ==
  
 +Directory: src/gui/editors/parameters
  
-gui/rosegardenguiiface.h+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.
  
-sequencer/rosegardensequenceriface.h+=== RosegardenMainViewWidget ===
  
-for definitions of the DCOP interfaces pertinent to the Sequencer and GUI. The main DCOP operations from the GUI involve starting and stopping the Sequencer, playing and recording, fast forwarding and rewinding. Once a play or record cycle is enabled it's the Sequencer that does most of the hard work. Events are read from (or written to, when recording) a set of mmapped files.+Directory: src/gui/application
  
 +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.
  
-The Sequencer makes use of two libraries libRosegardenSequencer and libRosegardenSound:+== TrackEditor ==
  
 +Directory: src/gui/editors/segment
  
 +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:
  
 +  * TrackButtons.
 +  * ChordNameRuler (invisible by default).
 +  * TempoRuler.
 +  * Top StandardRuler.
 +  * CompositionView.
 +  * Bottom StandardRuler.
  
-libRosegardenSequencer holds everything pertinent to sequencing for Rosegarden including the Sequencer class itself. This library is only linked into the Rosegarden Sequencer.+==== Dialogs ====
  
 +==== Editors ====
  
 +=== Matrix ===
 +=== Notation ===
 +=== Event List ===
  
-libRosegardenSound holds the MidiFile class (writing and reading MIDI files) and the MappedEvent and MappedComposition classes (the communication class for transferring events back and forth across DCOP). This library is needed by the GUI as well as the Sequencer.+===== The Audio classes =====
  
-The main Sequencer state machine is a good starting point and clearly visible at the bottom of rosegarden/sequencer/main.cpp. 
 
 
dev/overall_code_structure.txt · Last modified: 2022/05/06 16:07 (external edit)
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki