Lomse Hacking Guide
The internal model is an abstract representation for an LDP document, containing all necessary information to derive any other representation when needed. It is not oriented to any particular use (rendering, play back, printing, music analysis, ...) but try to serve all them equally. In this way the document can serve to the purpose of any view: a view can either be a print out of a conventional music score; or it can be a textual representation in LDP or any other language; or it can be a play back oriented representation, such a table of MIDI events; or any other representation for any purpose.
When a particular use is intended, the corresponding optimised representation is derived from the internal model. For instance, from InternalModel the following purpose dependent representations are currently derived by Lomse:
The internal representation or internal model is, basically, a tree of objects, derived from abstract class ImoObj. All these objects have ‘Imo’ as class prefix and are sometimes named in this document as IMOs: Internal Model Objects.
The root of the internal model tree is an object of class ImoDocument and represents the content of a LDP tag ‘lenmusdoc’, that is, a whole LDP document. The internal model tree follows, basically, the same structure than the LDP document. As LDP language describes content in a tree fashion (as XML does), the internal model mimics the LDP structure. For instance, the following LDP document:
(lenmusdoc (vers 0.0)
(content
(score (vers 1.6)
(instrument
(musicData
(clef G)
(key A)
(n a4 q)
(n c5 q)
)
)
)
)
)
will render the following score:
Internally, it will be represented as the following tree:
ImoDocument
|
ImoContent
|
ImoScore
|
ImoInstrument
|
ImoMusicData
|
+-------------+--+----------+---------+
| | | |
ImoClef ImoKeySignature ImoNote ImoNote
Even auxiliary data transfer objects, used only during model construction, derive from ImoObj. This is for uniform treatment in LDP compiler, resulting in a simpler design and better type checking. But there is practically no cost in deriving from ImoObj and it provides some benefits.
For documents containing only texts and images, such as HTML pages, a tree representation (i.e. the DOM) is normally good enough for processing. But for music scores there are two main issues to take into account.
To take these two issues into account in a pragmatic way, for music scores I added some additional information to the internal model tree:
For music scores, the tree structure representing the score content is complemented with an auxiliary representation, the ColStaffObjs object. It is oriented to traverse scores by voice and by time position. It is described in section The staff objects collection.
For music scores, IMOs representing relationships between other IMOs (i.e. ImoTie) have to be linked to the objects that form part of the relationship. But these relation objects can not be modelled as tree nodes as that would transform the tree in a network. For instance, the following score with two tied notes:
(score (vers 1.6)
(instrument
(musicData
(clef G)
(key C)
(n a4 q (tie 1 start))
(n a4 q (tie 1 stop))
)
)
)
would create the following invalid tree:
ImoScore
|
ImoInstrument
|
ImoMusicData
|
+-------------+--+----------+--------+
| | | |
ImoClef ImoKeySignature ImoNote ImoNote
\ /
\ /
ImoTie
For this reason, the notation object itself, ImoTie in previous example, is not included as part of the tree, but stored in a special container class. This is described in detail in section Auxiliary objects: classes ImoAuxObj and ImoRelObj.
The base class for internal model objects is ImoObj. From it, a hierachy of derived classes is created.
At the root of this hierarchy, ImoObj specializes in three main types:
Content objects (ImoContentObj) can be subdivided into two main groups (although no base class for them has been created): components, representing atomic objects and containers, that is objects that have components.
Specific objects for music score are divided into two main categories: staff objects and auxiliary objects. Staff objects represent the ‘main’ content of the music (basically notes, rests, clefs, key signatures and time signatures), that is, those objects that must me rendered on a staff and that are are positiones by time (music ‘events).
All other notations are considered auxiliary objects. In turn, there are two main types of auxiliary objects: those modelling a simple musical notation (i.e. a fermata, an accent, an attacehd text) and those modelling a relationship between objects (i.e. a tie, and slur, a dynamics wedge).
The following picture shows current hierarchy of objects. Those marked with ‘(A)’ are abstract classes. In some cases the equivalence to HTML tags is marked:
ImoObj (A) (type, id)
|
+-- ImoDto (A) () Data Transfer Objects (Dto suffix). Temporay use
| | during model building, but never part of the final
| | tree (the internal model)
| |
| +-- ImoFontStyleDto
| +-- ImoColorDto
| +-- ImoBeamDto
| +-- ImoSlurDto
| +-- ImoTieDto
| +-- ImoTupletDto
| +-- ImoBorderDto - not used!!!!
| +-- ImoPointDto - not used!!!!
| +-- ImoSizeDto - not used!!!!
|
|
+-- ImoSimpleObj (A) () No renderizable
| | They just contains other objects or properties
| |
| | ___________________________________________________________
| | === Value Objects to encapsulate data ==
| | Some of them are stored as nodes in the tree; others,
| | as member variables in other objects. Nevertheless,.
| | all defined as tree nodes for uniform treatment.
| |
| +-- ImoBezierInfo -- data (*) in SlurData, TieData, TieDto, SlurDto
| +-- (ImoFiguredBassInfo)
| +-- (ImoFigBassIntervalInfo)
| +-- ImoInstrGroup -- data in ImoInstrument(*)
| +-- ImoLineStyle -- data in ImoTextBox, ImoLine(*)
| +-- ImoMidiInfo -- data in ImoInstrument
| +-- ImoPageInfo -- data in ImoDocument, ImoScore
| +-- ImoStaffInfo -- data in ImoInstrument(list)
| +-- ImoSystemInfo -- data in ImoScore
| +-- ImoTextInfo (string, style) -- data in ImoScoreText
| |
| | // Nodes in tree
| |
| +-- ImoOptionInfo - node in ImoOptions
| +-- ImoParamInfo - node in ImoDynamics
| +-- ImoStyle - not node, but element in ImoStyles (std::map)
| |
| | ___________________________________________________________
| | === Value objects to contain relation data for a node =====
| |
| +-- ImoRelDataObj (A)
| | +-- ImoBeamData
| | +-- ImoSlurData
| | +-- ImoTieData
| | +-- ImoTupletData
| |
| | ___________________________________________________________
| | === Container objects; no additional properties ===========
| |
| +-- ImoCollection (A) () A node. Branches are the stored objs
| | |
| | +-- ImoMusicData <staffobj>
| | +-- ImoOptions <option>
| | +-- ImoInstruments <instrument>
| | +-- ImoInstrGroups <instrgroup>
| | +-- ImoAttachments <auxobj>
| |
| +-- ImoRelations <relobj> [a list to store relobjs]
| |
| +-- ImoContainerObj (A) ()
| |
| +-- ImoInstrument (... , [musicData])
|
|
+---ImoContentObj (A) (style, id, location, visible, [attachments])
|
+-- ImoBoxLevelObj (A)
| | Abstract class for all box-level objects
| |
| +-- ImoScore
| |
| +-- ImoBoxContainer (A)
| | | A box-level container for box-level objects. All
| | | ImoBoxContainer objects (except ImoContent and
| | | ImoDynamic) have a ImoContent object as container.
| | |
| | +-- ImoDocument [html/body]
| | +-- ImoContent [div] - a generic box-level container
| | | +-- ImoDynamic [object]
| | |
| | +-- ImoMultiColumn - a container subdivided in columns
| | +-- (ImoTable) [table]
| | +-- ImoList [ol, ul]
| |
| +-- ImoBoxContent (A)
| | A box-level container for inline-level objs.
| |
| +-- ImoParagraph [p]
| +-- ImoHeading [h1, h2, h3, h4, h5]
| +-- ImoListItem [li]
|
|
+-- ImoInlineObj (A)
| | Inline-level objects
| |
| |
| +-- ImoBoxInline (A) (size, content) - an abstract
| | | inline-level box container.
| | |
| | +-- ImoInlineWrapper [] - A generic inline-box container
| | +-- ImoLink [a] - Anchor
| |
| +-- ImoButton [button] - a button
| +-- ImoControl (control) - A user defined GUI obj.
| | +-- ImoScorePlayer - A control for managing score playback
| |
| +-- ImoTextItem [] - a piece of text with the same style
| +-- ImoImage [img] - Inline image
|
|
+-- ImoScoreObj (A) (color) content for scores
|
+-- ImoStaffObj (A) (timePos, numStaff)
| |
| +-- ImoBarline
| +-- ImoClef
| +-- ImoKeySignature
| +-- ImoMetronomeMark
| +-- ImoTimeSignature
| +-- ImoGoBackFwd
| +-- ImoSystemBreak
| +-- ImoSpacer
| +-- ImoNoteRest (A) (noteType, dots, voice)
| +-- ImoNote
| +-- ImoRest
|
+-- ImoAuxObj (A) () Can go attached to any score object
| +-- ImoFermata
| +-- ImoBlock (A)
| | +--- ImoTextBox (anchor line, paragraphs)
| |
| +-- ImoScoreLine
| +-- ImoScoreText (text-info)
| +-- ImoScoreTitle (h-align)
| ( +-- ImoInstrNameAbbrev )
|
+-- ImoRelObj (A) Relates two or more StaffObjs
+-- ImoTie
+-- ImoBeam
+-- ImoChord
+-- ImoSlur
+-- ImoTuplet