~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to docs/drafts/architecture/objects_model.txt

  • Committer: cecilios
  • Date: 2012-09-11 16:59:18 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:branches/TRY-5.0:730
Paths: fixed problem with installation folders. Fixed Chinese ISO language code

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Score objects model. Design rationale
2
 
--------------------------------------
3
 
 
4
 
 
5
 
Objects model: history and evolution
6
 
-----------------------------------
7
 
 
8
 
I didn't have any previous experience about modelling music and so I started by following the MusicXML model. A second reason to follow it was that a liked to implement export/import MusicXML and so, to simplify this objective, my internal representation should allow for easy conversion to/from MusicXML.
9
 
 
10
 
In MusicXML:
11
 
 
12
 
- Score is a collection of instruments (<parts>). Titles are directly owned by the score:
13
 
        <!ELEMENT score-partwise (%score-header;, part+)>
14
 
    
15
 
- <part> contains all measures for one instrument
16
 
        <!ELEMENT part (measure+)>
17
 
        
18
 
- <measure> contains all the information
19
 
        <!ELEMENT measure (%music-data;)>
20
 
        <!ENTITY % music-data
21
 
            "(note | backup | forward | direction | attributes |
22
 
            harmony | figured-bass | print | sound | barline | 
23
 
            grouping | link | bookmark)*">
24
 
        
25
 
- <notes> have additional elements, such as <notations><lyrics><technical><fermata>etc. Let me refer to all them by <notations>
26
 
        <!ELEMENT note 
27
 
        ( ( (grace, %full-note;, (tie, tie?)?) |
28
 
               (cue, %full-note;, duration) |
29
 
            (%full-note;, duration, (tie, tie?)?)),
30
 
          instrument?, %editorial-voice;, type?, dot*, accidental?, time-modification?,
31
 
          stem?, notehead?, staff?, beam*, notations*, lyric*)>
32
 
 
33
 
- <notations> are musical notations, not other elements (directions).
34
 
        <!ELEMENT notations
35
 
            (%editorial;, 
36
 
            (tied | slur | tuplet | glissando | slide | 
37
 
            ornaments | technical | articulations | dynamics |
38
 
            fermata | arpeggiate | non-arpeggiate | 
39
 
            accidental-mark | other-notation)*)>
40
 
            
41
 
- <directions> are not note-specific, and therefore might attach to a
42
 
    <part> or the overall score. i.e. texts
43
 
        <!ELEMENT direction (direction-type+, offset?,
44
 
            %editorial-voice;, staff?, sound?)>
45
 
        <!ELEMENT direction-type (rehearsal+ | segno+ | words+ |
46
 
            coda+ | wedge | dynamics+ | dashes | bracket | pedal | 
47
 
            metronome | octave-shift | harp-pedals | damp | 
48
 
            damp-all | eyeglasses | scordatura | other-direction)>
49
 
 
50
 
I also took into account that in the Sibelius model all objects are attached to an staff. As this was not in contradiction with the MusicXML model I started assuming that any object will be a StaffObj, even if it does not consume time. <directions> where the only exception but they can be considered as attached to the score, as well as titles: everything fitted perfectly.
51
 
 
52
 
When I started to implement <notations> I found that as they are attached to <notes> they did not fit in the lmStaffObj model. So I created a new class for <notations>: lmAuxObj
53
 
 
54
 
Also I created a more abstract class (ScoreObj) with two specializations: lmStaffObj and lmAuxObj. And specialized lmStaffObj: CompositeObj, for objects that can own <notations>, that is lmAuxObjs, (only notes/rests) and SimpleObj, for the remaining objects.
55
 
 
56
 
 
57
 
        
58
 
Objects model
59
 
--------------
60
 
 
61
 
A root class lmObject with two specializations: 
62
 
 
63
 
    - ContainerObj: main grouping elements: score, instrument, vstaff. As they do not share common operations I will not define (yet) an abstract class for them.
64
 
 
65
 
    - ScoreObj: Anything that can appear in an score
66
 
  
67
 
Container classes:
68
 
    lmScore: The top most container. A lmScore is, mainly, a collection of Instruments 
69
 
        plus some data (composer, title, ...). It also contains all independent objects.
70
 
        It contains:
71
 
        - collection of instruments (m_cInstruments)
72
 
        - list of score titles (m_cTitles)
73
 
        - collection of independent ScoreObjs (m_cGlobalStaffobjs). These are all those
74
 
            objects not directly associated to a musical object (notes, staff, etc.). 
75
 
            They are owned by nobody.
76
 
        
77
 
    lmInstrument: A container for the ScoreObjs associated to one instrument:
78
 
        - List of VStaves that this instrument has (m_cStaves)
79
 
 
80
 
    lmVStaff: Container for the ScoreObjs on this VStaff (m_cStaffObjs)
81
 
 
82
 
ScoreObj is specialized in three:
83
 
 
84
 
    - StaffObj: objects attached to an VStaff (measure). In this group we have the main musical elements, normally with duration (notes/rests) or time positioned (clef, key signature, time signature). They are in a staff/measure, so they are attached to an VStaff. They normally 'consume' time and so measuring phase is done by time position and Draw() is done
85
 
    in two phases controlled just by its timePos.
86
 
 
87
 
    - AuxObj: objects attached not to a staff but to one or more StaffObj. For example, to one StaffObj: a note plus its accidental symbol; caesura marks, texts, and some <notations> (i.e. articulations) attached to notes; repeat signs attached to barlines, etc. To two StaffObj: ties attached to two notes, wedges for dynamics, etc. As the do not consume time, the measuring phase is done by specific methods, controlled by owner objects.
88
 
 
89
 
    - GraphicObj (graphics): elements with no musical meaning for the program. So, from a program point of view they are just 'decoration': text (different from lyrics or other meaningful texts), lines, arrows. boxes, markup and visual emphasis, some <notations> (i.e. articulations), etc. They can be attached both to StaffObj and to AuxObj. 
90
 
    For example: to put a coloured box around a caesura mark, with an arrow pointing to it and a text attached to the arrow. This can be achieved be drawing a box, an arrow and the text, positioning them as desired, grouping them to form a compound graphic object and attaching this GraphObj to the caesura AuxObj.
91
 
    No measuring phase needed as they are always parent anchored (relative dx,dy to parent m_paperPos).
92
 
 
93
 
    A GraphObj is not an StaffObj and, so it can not be attached directly to an staff. In order to allow for placing GraphObjs on the staff it is necessary to create an 'empty' StaffObj. This empty StaffObj could have width so it can also be used as a 'spacer'.
94
 
 
95
 
    GraphObj are compound objs, that is, they can be formed by aggregation of simpler GraphObj.
96
 
 
97
 
 
98
 
Finally, I defined other auxiliary objects non-derived from lmObject:
99
 
    
100
 
    lmBeam:     info about the beam for a group of notes
101
 
    lmChord:    info about a chord
102
 
    lmArch:     info to draw an arch
103
 
    lmContext:  info about current accidentals 
104
 
    lmBasicText: info for a text (font size, font family, ..)
105
 
    lmStaff:    Properties for each staff on a VStaff (num.lines, spacing, ...)
106
 
 
107
 
 
108
 
Current defined lmStaffObj:
109
 
        
110
 
    - not owning lmAuxObjs
111
 
        
112
 
        lmBarline, lmClef, lmWordsDirection, lmKeySignature, lmSOControl,
113
 
        lmScoreText, lmTimeSignature, lmTupletBracket, lmMetronomeMark
114
 
 
115
 
    - can own lmAuxObjs
116
 
        
117
 
        lmNoteRest (lmNote, lmRest)
118
 
       
119
 
 
120
 
Currently (to be reviewed) lmAuxObj (do not consume time ==> owned by the Score)
121
 
        Other symbols, related either to an staff, to the score (paper) or
122
 
        to other ScoreObjs, that do not "take time". Examples of this group objects are
123
 
        texts, slurs, ties, lyrics and note accidentals.
124
 
        
125
 
        As the owner is not the lmVStaff but other object (i.e.: Ties are owned by Notes, 
126
 
        scores titles are owned by the lmScore) they are not included in the lmVStaff
127
 
        objects collection. Therefore, certain operations such as renderization are not
128
 
        triggered by the VStaff. 
129
 
        To deal with these AuxObjs in a uniform way for common functions such
130
 
        as selecting, dragging, etc., they will be included in a global list,
131
 
        so that all these functions can be easily implemented by just iterating over
132
 
        this collection.
133
 
        
134
 
        For some other functions, such as rendering, the uniform approach could not be so
135
 
        feasible as renderization will be launched sometimes by the owner lmStaffObj
136
 
        (i.e. Ties)
137
 
        and other times centrally, by iterating over the list and rendering the objects
138
 
        in it (i.e. lmScore titles). In these cases, it will be necessary to include
139
 
        flags to signal that the operation will be performed by the owner and, so,
140
 
        to skip that object.
141
 
        
142
 
        Current lmAuxObjs:
143
 
            lmTie
144
 
            
145
 
            lmNoteRestObj
146
 
                AuxObjs related to NoteRests. The rendering is controlled by the owner
147
 
                lmNoteRest and the measurement and drawing phases are implemented by
148
 
                two different methods instead
149
 
                of the combined method Draw() used by StaffObjs.
150
 
        
151
 
                Current:
152
 
                    lmFermata
153
 
                    lmLyric
154
 
                    lmAccidental                
155
 
 
156
 
 
157
 
 
158
 
 
159
 
 
160
 
 
161
 
Types of elements to consider and implementation criteria
162
 
----------------------------------------------------------
163
 
 
164
 
1. Elements with musical meaning directly on an staff and affecting only to that staff: notes, rests, clefs, keys, barlines, etc. ==> modelled by StaffObj
165
 
 
166
 
2. Elements with musical meaning not directly on an staff but associated to elements on the staff and affecting only to them. For example: attached to notes/rests (ties, slurs, fermata, lyrics, accidentals, articulations, technical markup, etc.  ==> modelled by AuxObj
167
 
 
168
 
3. Elements with musical meaning that can not be associated to elements on the staff, and affecting not only to one staff but to the system. These include tempo (metronome marks), text (dynamics texts) and rehearsal marks. ==> modelled by StaffObj
169
 
 
170
 
4. Elements with no musical meaning but with meaning for the program. For example system and page breaks. ==> modelled by StaffObj
171
 
 
172
 
5. Elements with no meaning at all for the program. So, from a program point of view they are just 'decoration': text (different from lyrics or other meaningful texts), lines, arrows. boxes,  etc.  ==> modelled by GraphObj attached either to AuxObj or to StaffObj
173
 
 
174
 
 
175
 
The difference between AuxObj and GraphicObj is sometimes fuzzy. For example: Lyrics are text; therefore, should we model them as GraphicObjs or as AuxObjs? Two criteria will help:
176
 
 
177
 
1. Is it going to be treated by the program just as 'decoration' or is there any possibility to perform some future 'musical' processing? For example, in future a feature to sing tunes could be added and, in this case, lyrics need to be 'understandable' by the program and should be modelled as AuxObj. Otherwise, if the program does not need to know the semantics of the element it is simpler to treat it as a GraphicObj.
178
 
 
179
 
2. For auto-layout, is it 'user positioned' or its positioning is complex? If it is user positioned it should be treated as a GraphicObj.
180
 
 
181
 
 
182
 
 
183
 
Attachment of GraphicObj to containers
184
 
---------------------------------------------
185
 
 
186
 
Should we allow direct attachment of graphic objs to containers (the score, a page, an staff, etc.)?
187
 
 
188
 
With GraphicObj no measuring phase needed as they are always parent anchored (relative dx,dy to parent m_paperPos). But, where is the origin (m_paperPos) for containers?
189
 
 
190
 
Probably it is non-sense to have GraphicObj attached to containers, other that the score. For the score, origin is paper origin of current page, so Draw should be launched by the BoxPage object. For other containers (lmInstrument, lmVStaff) the lmGraphicObj should be attached to an StaffObj or to a measure (in fact the barline StaffObj), and Draw() should be launched by the parent Draw method.
191
 
 
192
 
The consequence is that only StaffObjs and the score can have other objects attached. This is compatible with MusicXML as all elements are part of a measure (I think it is an heritage of the initial MusicXML structure. The second consequence of this heritage is that the only objects attached to the score are the score titles). In Sibelious also all elements must be in a system. 
193
 
 
194
 
But all this is consequence of the linear storage model imposed by MusicXML. In a score editor it should be feasible to attach objects and properties to any part. Let's analyse how to implement some examples to get knowledge to take a decision.
195
 
 
196
 
Example 1. The user selects a system on page 2 and add a border frame to it and to change its background colour. 
197
 
The user interacts with the GR (BoxSystem) and any object/property attached to that system could be stored in the first measure of that system. This will comply with MusicXML structure.
198
 
 
199
 
Example 2. User selects a page and attach a text to it. 
200
 
The user interacts with the GR (BoxPage) and any object/property attached to that system could be stored in the first system of that page. This in turn implies (example 1) to attach the object/property in the first measure of that system.
201
 
 
202
 
    Conclusion
203
 
    -----------
204
 
    
205
 
There is no need to attach GraphObj to the Score as we can attach them to the firts measure. This will force to move titles from the score. Does it worth moving them? 
206
 
 
207
 
In favour:
208
 
    - Uniform object model: GraphObjs only attached to AuxObj and StaffObj
209
 
    - Could lose flexibility? --> It does not appear to.
210
 
 
211
 
Against:
212
 
    - Titles will not be identifyied as 'titles' but as 'grafic objects'. Therefore we lose
213
 
        semantics. Problems to export to MusicXML and other formats. 
214
 
    
215
 
    
216
 
So to avoid losing semantics and as it is already implemented, let's leave the titles in the Score.
217
 
 
218
 
 
219
 
 
220
 
 
221
 
=============================================================================================
222
 
Summary: Objects, properties and main behaviour/purpose
223
 
=============================================================================================
224
 
 
225
 
 
226
 
lmObject
227
 
--------
228
 
 
229
 
    - Can have options (m_pObjOptions)
230
 
 
231
 
 
232
 
lmScoreObj
233
 
-------------
234
 
Any object displayed on the score:
235
 
 
236
 
    - They have type and identification number (m_nType, m_nId)
237
 
    - Could be draggable (m_fIsDraggable)
238
 
    - They have positioning info: origin (m_paperPos), page num (m_nNumPage)
239
 
    - Could be selected, so they have a selection rectangle (m_fSelected, m_selRect)
240
 
    - can be rendered (methods: Draw, GetBitmap) Two phases draw. Invoke DrawObject.
241
 
    - Can have Graphic objects attached (m_pAuxObjs)
242
 
 
243
 
    - Dump method
244
 
    
245
 
    Optional:
246
 
    - Can be font rendered (m_pFont, m_glyphPos)
247
 
    - Can be Shape rendered (m_fShapeRendered m_pShape)
248
 
 
249
 
 
250
 
lmStaffObj
251
 
----------
252
 
Objects on the Staff.
253
 
 
254
 
    - Measuring phase is done by time position
255
 
    
256
 
    - They can have duration (time positioned: m_rTimePos)
257
 
    - They are related to an Staff (m_pVStaff, m_nStaffNum, m_numMeasure)
258
 
    - They can own objects lmAuxObj and lmGraphicObj
259
 
    - Source code methods (SourceLDP, SourceXML)
260
 
    
261
 
lmAuxObj
262
 
----------
263
 
Objetcs attached to StaffObjs.
264
 
 
265
 
    - Measuring phase is done by specific methods, controlled by owner StaffObj
266
 
    - They can own objects lmGraphicObj
267
 
    - No source code methods. Source code generated by owner StaffObj.
268
 
    
269
 
lmGraphicObj
270
 
---------------
271
 
    - No measuring phase. Parent anchored (relative dx,dy to parent m_paperPos).
272
 
    - Recursive composition (aggregation)
273
 
    
274
 
    
275
 
    
276
 
    
277
 
    
278
 
lmScore
279
 
------------
280
 
    - play methods (Play, PlayMeasure, Pause, Stop, WaitForTermination)
281
 
    - serving highlight events (ScoreHighlight)
282
 
    - Dump methods (Dump, DumpMidiEvents)
283
 
    - Source code methods (SourceLDP, SourceXML)
284
 
    - Manage instruments
285
 
    - Manage score titles
286
 
    - identification (score name, m_nID)
287
 
 
288
 
    InstrumentsList     m_cInstruments;     //list of instruments that form this score
289
 
    StaffObjsList       m_cTitles;          //list of score titles
290
 
    StaffObjsList   m_cGlobalStaffobjs;     //list of other StaffObjs not included in an lmVStaff
291
 
 
292
 
 
293
 
lmInstrument
294
 
-------------
295
 
    - VStaff management (m_cStaves)
296
 
    - Dump method
297
 
    - Source code methods (SourceLDP, SourceXML)
298
 
    - MIDI configuration (m_nMidiInstr, m_nMidiChannel)
299
 
    - Instrument name and indentation (m_nIndentFirst, m_nIndentOther, m_pName, m_pAbbreviation)
300
 
 
301
 
    VStavesList     m_cStaves;          //wxList of VStaves that this instrument has
302
 
 
303
 
 
304
 
lmVStaff
305
 
-------------
306
 
    - Staff management
307
 
    - Clef management
308
 
    - Time signature management
309
 
    - Key signature management
310
 
    - notes and rests management
311
 
    - barlines management
312
 
    - control ScoreObjs management (AddNewSystem, ShiftTime)
313
 
    - words directions management
314
 
    - Measures management (GetNumMeasures)
315
 
    - Rendering methods (DrawStaffLines, DrawProlog, NewLine, SetUpFonts, GetStaffLineThick)
316
 
    - renderization helper methods (GetXPosFinalBarline)
317
 
    - Units conversion (TenthsToLogical)
318
 
    - Dump method
319
 
    - Source code methods (SourceLDP, SourceXML)
320
 
 
321
 
    - notes context management
322
 
    - sound related methods (ComputeMidiEvents)
323
 
    
324
 
    
325
 
    lmColStaffObjs      m_cStaffObjs;   //collection of StaffObjs
326
 
    StaffList           m_cStaves;      //list of Staves (lmStaff objects)  
327
 
 
328
 
 
329
 
 
330
 
 
331
 
=============================================================================================
332
 
 
333
 
 
334
 
 
335
 
 
336
 
Selection (selectable objects)
337
 
------------------------------
338
 
    ScoreObjs are selectable by definition, as the user should be able to select (and copy,
339
 
    delete, move, ...) any rendered object. But the procedure to select an object will
340
 
    vary. Simple objects, such as notes or clefs, will have a clear bounding rectangle, that
341
 
    normally will not intersect the bound ling rectangle of neighbour objects; selection 
342
 
    can be done just by clicking with the mouse on this selection rectangle. Other objects,
343
 
    such an instrument's staff or the whole score, could be difficult to select by this method
344
 
    as either (1) will not have associated a selection rectangle (i.e. an instrument's staff, 
345
 
    as it goes across a lot of pages), or (2) will conflict with too many other selection
346
 
    rectangles (i.e. the staff lines or the whole score). Therefore, for these composite
347
 
    objects we will need a different approach for selection.
348
 
    
349
 
    So, we will call "RectSelectable objects" only to those of the first type: the will have a 
350
 
    clear bounding selection rectangle and selection can be implemented just by clicking
351
 
    on this rectangle with the mouse. The other ScoreObjs will have a different 
352
 
    procedure for selection but not a selection rectangle. 
353
 
    
354
 
    
355
 
-----------------------------------------------------------------------------------------
356
 
-----------------------------------------------------------------------------------------
357
 
    We could consider five types of positioning methods:
358
 
    1.    TimeParallel: All ScoreObjs with the same timepos must be rendered aligned at 
359
 
        the same x position. (only Notes and Rests)
360
 
    2.    TimeSequencial: All ScoreObjs with the same timepos will be rendered along
361
 
        the x axis in sequence, in the same sequence as they where created (clefs and keys)
362
 
    3.    Indirect: Its positioning coordinates are predefined by the position of the
363
 
        owner ScoreObjs.
364
 
    4.    FixedAbs: pre-defined, by specifying its absolute positioning coordinates (that
365
 
        is, referred to page origin).
366
 
    5.    FixedRel: pre-defined, by specifying its positioning coordinates, relative to
367
 
        a barline.
368
 
 
369
 
    TimePositionedObj:
370
 
        ScoreObjs that, by necessity, must go in sequence in a staff (such as notes, 
371
 
        rests, clefs and keys). When one of these signs appear they add time to the
372
 
        measure duration. Therefore, they have timing information.
373
 
        
374
 
    RelativePositionedObj:
375
 
        Its position is relative to the position of the owner:
376
 
        - owned by page: page origin.
377
 
        - owned by barline: barline position
378
 
        - owned by an lmScoreObj (i.e. note): lmScoreObj position
379
 
 
380
 
-----------------------------------------------------------------------------------------
381
 
-----------------------------------------------------------------------------------------
382
 
    Considering positioning and sizing, a lmScoreObj can be of two types:
383
 
        - draggable: the objects can be freely positioned on the score, only constrained
384
 
            by music writing rules (i.e.: note, clef).
385
 
        - sizable: the object size is not fully restricted by staff size or other and so,
386
 
            can be someway resized. The object is rendered with handle marks for
387
 
            resizing (i.e.: slur, tie, text)
388
 
 
389
 
-----------------------------------------------------------------------------------------
390
 
    
391
 
 
392
 
 
393
 
 
394
 
============================================================================================
395
 
Move to architecture:
396
 
============================================================================================
397
 
 
398
 
lmFormatter:
399
 
    Because formatting algorithms tend to be complex, it's also desirable to keep them 
400
 
    well contained and, if possible, completely independent of the document structure.
401
 
    We will define a separate class hierarchy for objects that encapsulate formatting
402
 
    algorithms. The root object is the class "lmFormatter".
403
 
    
404
 
 
405