musa-dsl 0.14.32 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/README.md +5 -1
  4. data/lib/musa-dsl.rb +54 -11
  5. data/lib/musa-dsl/core-ext.rb +7 -13
  6. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +15 -23
  7. data/lib/musa-dsl/core-ext/arrayfy.rb +30 -12
  8. data/lib/musa-dsl/core-ext/attribute-builder.rb +194 -0
  9. data/lib/musa-dsl/core-ext/deep-copy.rb +185 -0
  10. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +44 -40
  11. data/lib/musa-dsl/core-ext/inspect-nice.rb +40 -22
  12. data/lib/musa-dsl/core-ext/smart-proc-binder.rb +108 -0
  13. data/lib/musa-dsl/core-ext/with.rb +26 -0
  14. data/lib/musa-dsl/datasets.rb +8 -3
  15. data/lib/musa-dsl/datasets/dataset.rb +3 -0
  16. data/lib/musa-dsl/datasets/delta-d.rb +12 -0
  17. data/lib/musa-dsl/datasets/e.rb +61 -0
  18. data/lib/musa-dsl/datasets/gdv.rb +51 -411
  19. data/lib/musa-dsl/datasets/gdvd.rb +179 -0
  20. data/lib/musa-dsl/datasets/helper.rb +41 -0
  21. data/lib/musa-dsl/datasets/p.rb +68 -0
  22. data/lib/musa-dsl/datasets/packed-v.rb +19 -0
  23. data/lib/musa-dsl/datasets/pdv.rb +22 -15
  24. data/lib/musa-dsl/datasets/ps.rb +113 -0
  25. data/lib/musa-dsl/datasets/score.rb +210 -0
  26. data/lib/musa-dsl/datasets/score/queriable.rb +48 -0
  27. data/lib/musa-dsl/datasets/score/render.rb +31 -0
  28. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +160 -0
  29. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +51 -0
  30. data/lib/musa-dsl/datasets/score/to-mxml/process-time.rb +153 -0
  31. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +158 -0
  32. data/lib/musa-dsl/datasets/v.rb +23 -0
  33. data/lib/musa-dsl/generative.rb +5 -5
  34. data/lib/musa-dsl/generative/backboner.rb +274 -0
  35. data/lib/musa-dsl/generative/darwin.rb +102 -96
  36. data/lib/musa-dsl/generative/generative-grammar.rb +182 -187
  37. data/lib/musa-dsl/generative/markov.rb +56 -53
  38. data/lib/musa-dsl/generative/variatio.rb +234 -222
  39. data/lib/musa-dsl/logger.rb +1 -0
  40. data/lib/musa-dsl/logger/logger.rb +31 -0
  41. data/lib/musa-dsl/matrix.rb +1 -0
  42. data/lib/musa-dsl/matrix/matrix.rb +210 -0
  43. data/lib/musa-dsl/midi.rb +2 -2
  44. data/lib/musa-dsl/midi/midi-recorder.rb +54 -52
  45. data/lib/musa-dsl/midi/midi-voices.rb +183 -182
  46. data/lib/musa-dsl/music.rb +5 -5
  47. data/lib/musa-dsl/music/chord-definition.rb +54 -50
  48. data/lib/musa-dsl/music/chord-definitions.rb +13 -9
  49. data/lib/musa-dsl/music/chords.rb +236 -238
  50. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +187 -183
  51. data/lib/musa-dsl/music/scales.rb +331 -332
  52. data/lib/musa-dsl/musicxml.rb +1 -0
  53. data/lib/musa-dsl/musicxml/builder/attributes.rb +155 -0
  54. data/lib/musa-dsl/musicxml/builder/backup-forward.rb +45 -0
  55. data/lib/musa-dsl/musicxml/builder/direction.rb +322 -0
  56. data/lib/musa-dsl/musicxml/builder/helper.rb +90 -0
  57. data/lib/musa-dsl/musicxml/builder/measure.rb +137 -0
  58. data/lib/musa-dsl/musicxml/builder/note-complexities.rb +152 -0
  59. data/lib/musa-dsl/musicxml/builder/note.rb +577 -0
  60. data/lib/musa-dsl/musicxml/builder/part-group.rb +44 -0
  61. data/lib/musa-dsl/musicxml/builder/part.rb +67 -0
  62. data/lib/musa-dsl/musicxml/builder/pitched-note.rb +126 -0
  63. data/lib/musa-dsl/musicxml/builder/rest.rb +117 -0
  64. data/lib/musa-dsl/musicxml/builder/score-partwise.rb +120 -0
  65. data/lib/musa-dsl/musicxml/builder/typed-text.rb +43 -0
  66. data/lib/musa-dsl/musicxml/builder/unpitched-note.rb +112 -0
  67. data/lib/musa-dsl/neumalang.rb +1 -1
  68. data/lib/musa-dsl/neumalang/datatypes.citrus +79 -0
  69. data/lib/musa-dsl/neumalang/neuma.citrus +165 -0
  70. data/lib/musa-dsl/neumalang/neumalang.citrus +32 -242
  71. data/lib/musa-dsl/neumalang/neumalang.rb +373 -142
  72. data/lib/musa-dsl/neumalang/process.citrus +21 -0
  73. data/lib/musa-dsl/neumalang/terminals.citrus +67 -0
  74. data/lib/musa-dsl/neumalang/vectors.citrus +23 -0
  75. data/lib/musa-dsl/neumas.rb +5 -0
  76. data/lib/musa-dsl/neumas/array-to-neumas.rb +34 -0
  77. data/lib/musa-dsl/neumas/neuma-decoder.rb +63 -0
  78. data/lib/musa-dsl/neumas/neuma-gdv-decoder.rb +57 -0
  79. data/lib/musa-dsl/neumas/neuma-gdvd-decoder.rb +15 -0
  80. data/lib/musa-dsl/neumas/neumas.rb +37 -0
  81. data/lib/musa-dsl/neumas/string-to-neumas.rb +33 -0
  82. data/lib/musa-dsl/repl.rb +1 -1
  83. data/lib/musa-dsl/repl/repl.rb +103 -110
  84. data/lib/musa-dsl/sequencer.rb +1 -1
  85. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +163 -136
  86. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +301 -286
  87. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +548 -321
  88. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +198 -176
  89. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +77 -0
  90. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +75 -0
  91. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +105 -85
  92. data/lib/musa-dsl/sequencer/timeslots.rb +34 -0
  93. data/lib/musa-dsl/series.rb +1 -1
  94. data/lib/musa-dsl/{core-ext → series}/array-to-serie.rb +1 -1
  95. data/lib/musa-dsl/series/base-series.rb +171 -168
  96. data/lib/musa-dsl/series/hash-serie-splitter.rb +134 -132
  97. data/lib/musa-dsl/series/holder-serie.rb +1 -1
  98. data/lib/musa-dsl/series/main-serie-constructors.rb +6 -1
  99. data/lib/musa-dsl/series/main-serie-operations.rb +807 -797
  100. data/lib/musa-dsl/series/proxy-serie.rb +6 -6
  101. data/lib/musa-dsl/series/queue-serie.rb +5 -5
  102. data/lib/musa-dsl/series/series.rb +2 -0
  103. data/lib/musa-dsl/transcription.rb +4 -0
  104. data/lib/musa-dsl/transcription/from-gdv-to-midi.rb +227 -0
  105. data/lib/musa-dsl/transcription/from-gdv-to-musicxml.rb +36 -0
  106. data/lib/musa-dsl/transcription/from-gdv.rb +17 -0
  107. data/lib/musa-dsl/transcription/transcription.rb +55 -0
  108. data/lib/musa-dsl/transport.rb +6 -6
  109. data/lib/musa-dsl/transport/clock.rb +26 -26
  110. data/lib/musa-dsl/transport/dummy-clock.rb +32 -30
  111. data/lib/musa-dsl/transport/external-tick-clock.rb +21 -20
  112. data/lib/musa-dsl/transport/input-midi-clock.rb +82 -80
  113. data/lib/musa-dsl/transport/timer-clock.rb +72 -71
  114. data/lib/musa-dsl/transport/timer.rb +28 -26
  115. data/lib/musa-dsl/transport/transport.rb +100 -95
  116. data/musa-dsl.gemspec +3 -3
  117. metadata +73 -24
  118. data/lib/musa-dsl/core-ext/array-apply-get.rb +0 -18
  119. data/lib/musa-dsl/core-ext/array-to-neumas.rb +0 -28
  120. data/lib/musa-dsl/core-ext/as-context-run.rb +0 -44
  121. data/lib/musa-dsl/core-ext/duplicate.rb +0 -134
  122. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +0 -85
  123. data/lib/musa-dsl/core-ext/proc-nice.rb +0 -13
  124. data/lib/musa-dsl/core-ext/send-nice.rb +0 -21
  125. data/lib/musa-dsl/core-ext/string-to-neumas.rb +0 -27
  126. data/lib/musa-dsl/datasets/gdv-decorators.rb +0 -221
  127. data/lib/musa-dsl/generative/rules.rb +0 -282
  128. data/lib/musa-dsl/neuma.rb +0 -1
  129. data/lib/musa-dsl/neuma/neuma.rb +0 -181
@@ -0,0 +1,44 @@
1
+ require_relative 'helper'
2
+
3
+ module Musa
4
+ module MusicXML
5
+ module Builder
6
+ module Internal
7
+ class PartGroup
8
+ include Helper
9
+ include Helper::HeaderToXML
10
+
11
+ def initialize(number = nil, # number
12
+ type:,
13
+ name: nil,
14
+ abbreviation: nil,
15
+ symbol: nil,
16
+ group_barline: nil, # true
17
+ group_time: nil) # true
18
+ @number = number
19
+ @type = type
20
+ @name = name
21
+ @abbreviation = abbreviation
22
+ @symbol = symbol
23
+ @group_barline = group_barline
24
+ @group_time = group_time
25
+ end
26
+
27
+ attr_accessor :number, :type, :name, :abbreviation, :symbol, :group_barline, :group_time
28
+
29
+ def _header_to_xml(io, indent:, tabs:)
30
+ io.puts "#{tabs}<part-group#{ decode_bool_or_string_attribute(@number&.to_i, 'number') } type=\"#{@type}\">"
31
+
32
+ io.puts "#{tabs}\t<group-name>#{@name}</group-name>" if @name
33
+ io.puts "#{tabs}\t<group-abbreviation>#{@abbreviation}</group-abbreviation>" if @abbreviation
34
+ io.puts "#{tabs}\t<group-symbol>#{@symbol}</group-symbol>" if @symbol
35
+ io.puts "#{tabs}\t<group-barline>#{decode_bool_or_string_value(@group_barline, 'yes', 'no')}</group-barline>" if @group_barline
36
+ io.puts "#{tabs}\t<group-time>#{decode_bool_or_string_value(@group_time, 'yes', 'no')}</group-time>" if @group_time
37
+
38
+ io.puts "#{tabs}</part-group>"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../../core-ext/with'
2
+
3
+ require_relative 'measure'
4
+
5
+ require_relative 'helper'
6
+
7
+ module Musa
8
+ module MusicXML
9
+ module Builder
10
+ module Internal
11
+ class Part
12
+ extend Musa::Extension::AttributeBuilder
13
+ include Musa::Extension::With
14
+
15
+ include Helper::HeaderToXML
16
+ include Helper::ToXML
17
+
18
+ def initialize(id, name:, abbreviation: nil, **first_measure_attributes, &block)
19
+ @id = id
20
+ @name = name
21
+ @abbreviation = abbreviation
22
+
23
+ @measures = []
24
+
25
+ unless first_measure_attributes.empty?
26
+ add_measure **first_measure_attributes
27
+ end
28
+
29
+ with &block if block_given?
30
+ end
31
+
32
+ attr_simple_builder :id
33
+ attr_simple_builder :name
34
+ attr_simple_builder :abbreviation
35
+
36
+ attr_complex_adder_to_custom :measure, variable: :@measures do
37
+ | divisions: nil,
38
+ key_cancel: nil, key_fifths: nil, key_mode: nil,
39
+ time_senza_misura: nil, time_beats: nil, time_beat_type: nil,
40
+ clef_sign: nil, clef_line: nil, clef_octave_change: nil |
41
+
42
+ Measure.new(@measures.size + 1,
43
+ divisions: divisions,
44
+ key_cancel: key_cancel, key_fifths: key_fifths, key_mode: key_mode,
45
+ time_senza_misura: time_senza_misura, time_beats: time_beats, time_beat_type: time_beat_type,
46
+ clef_sign: clef_sign, clef_line: clef_line, clef_octave_change: clef_octave_change).tap { |measure| @measures << measure }
47
+ end
48
+
49
+ def _header_to_xml(io, indent:, tabs:)
50
+ io.puts "#{tabs}<score-part id=\"#{@id}\">"
51
+ io.puts "#{tabs}\t<part-name>#{@name}</part-name>"
52
+ io.puts "#{tabs}\t<part-abbreviation>#{@abbreviation}</part-abbreviation>" if @abbreviation
53
+ io.puts "#{tabs}</score-part>"
54
+ end
55
+
56
+ def _to_xml(io, indent:, tabs:)
57
+ io.puts "#{tabs}<part id=\"#{@id}\">"
58
+ @measures.each do |measure|
59
+ measure.to_xml(io, indent: indent + 1)
60
+ end
61
+ io.puts "#{tabs}</part>"
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,126 @@
1
+ require_relative 'note'
2
+
3
+ module Musa
4
+ module MusicXML
5
+ module Builder
6
+ module Internal
7
+ class PitchedNote < Note
8
+ def initialize(_step = nil, step: nil, alter: nil, octave:,
9
+ pizzicato: nil, # true
10
+ grace: nil, # true
11
+ cue: nil, # true
12
+ chord: nil, # true
13
+ duration: nil, # number positive divisions
14
+ tie_start: nil, tie_stop: nil, # true
15
+ voice: nil, # number
16
+ type: nil, # whole / half / quarter / ...
17
+ dots: nil, # number
18
+ accidental: nil, # sharp / flat / ...
19
+ time_modification: nil, # TimeModification class instance
20
+ stem: nil, # up / down / double
21
+ notehead: nil, # Notehead class instance
22
+ staff: nil, # number
23
+
24
+ # notations
25
+ accidental_mark: nil, # sharp / natural / flat / ...
26
+ arpeggiate: nil, # true / up / down
27
+
28
+ tied: nil, # start / stop / continue
29
+ tuplet: nil, # Tuplet class instance
30
+
31
+ dynamics: nil, # pppp...ffff (single or array of)
32
+ fermata: nil, # true / upright / inverted
33
+ glissando: nil, # start / stop
34
+ non_arpeggiate: nil, # top / bottom
35
+
36
+ slide: nil, # start / stop
37
+ slur: nil, # start / stop / continue
38
+
39
+ ## articulations
40
+ accent: nil, # true
41
+ breath_mark: nil, # comma / tick
42
+ caesura: nil, # true
43
+ detached_legato:nil, # true
44
+ doit: nil, # true
45
+ falloff: nil, # true
46
+ other_articulation: nil, # text
47
+ plop: nil, # true
48
+ scoop: nil, # true
49
+ spiccato: nil, # true
50
+ staccatissimo: nil, # true
51
+ staccato: nil, # true
52
+ stress: nil, # true
53
+ strong_accent: nil, # true / up / down
54
+ tenuto: nil, # true
55
+ unstress: nil, # true
56
+
57
+ ## ornaments
58
+ delayed_inverted_turn: nil, # true
59
+ delayed_turn: nil, # true
60
+ inverted_mordent: nil, # true
61
+ inverted_turn: nil, # true
62
+ mordent: nil, # true
63
+ schleifer: nil, # true
64
+ shake: nil, # true
65
+ tremolo: nil, # start / stop / single,
66
+ trill_mark: nil, # true
67
+ turn: nil, # true
68
+ vertical_turn: nil, # true
69
+ wavy_line: nil, # true
70
+ other_ornament: nil, # true
71
+ ornament_accidental_mark: nil, # sharp / natural / flat / ...
72
+
73
+ ## technical
74
+ arrow: nil, # Arrow class instance
75
+ bend: nil, # Bend class instance
76
+ double_tongue: nil, # true
77
+ down_bow: nil, # true
78
+ fingering: nil, # Fingering class instance
79
+ fingernails: nil, # true
80
+ fret: nil, # number
81
+ hammer_on: nil, # HammerOnPullOff class instance
82
+ handbell: nil, # damp / echo / ...
83
+ harmonic: nil, # Harmonic class instance
84
+ heel: nil, # true
85
+ hole: nil, # Hole class instance
86
+ open_string: nil, # true
87
+ other_technical: nil, # text
88
+ pluck: nil, # text
89
+ pull_off: nil, # HammerOnPullOff class insstance
90
+ snap_pizzicato: nil, # true
91
+ stopped: nil, # true
92
+ string: nil, # number (string number)
93
+ tap: nil, # text
94
+ thumb_position: nil, # true
95
+ toe: nil, # true
96
+ triple_tongue: nil, # true
97
+ up_bow: nil, # true
98
+ &block)
99
+
100
+ @step = step || _step
101
+ @alter = alter
102
+ @octave = octave
103
+
104
+ super
105
+ end
106
+
107
+ attr_simple_builder :step
108
+ attr_simple_builder :alter
109
+ attr_simple_builder :octave
110
+
111
+ private
112
+
113
+ def specific_to_xml(io, indent:)
114
+ tabs = "\t" * indent
115
+
116
+ io.puts "#{tabs}<pitch>"
117
+ io.puts "#{tabs}\t<step>#{@step}</step>"
118
+ io.puts "#{tabs}\t<alter>#{@alter}</alter>" if @alter
119
+ io.puts "#{tabs}\t<octave>#{@octave.to_i}</octave>"
120
+ io.puts "#{tabs}</pitch>"
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,117 @@
1
+ require_relative 'note'
2
+
3
+ module Musa
4
+ module MusicXML
5
+ module Builder
6
+ module Internal
7
+ class Rest < Note
8
+ def initialize(pizzicato: nil, # true
9
+ measure: nil, # true
10
+ grace: nil, # true
11
+ cue: nil, # true
12
+ chord: nil, # true
13
+ duration: nil, # number positive divisions
14
+ tie_start: nil, tie_stop: nil, # true
15
+ voice: nil, # number
16
+ type: nil, # whole / half / quarter / ...
17
+ dots: nil, # number
18
+ accidental: nil, # sharp / flat / ...
19
+ time_modification: nil, # TimeModification class instance
20
+ stem: nil, # up / down / double
21
+ notehead: nil, # Notehead class instance
22
+ staff: nil, # number
23
+
24
+ # notations
25
+ accidental_mark: nil, # sharp / natural / flat / ...
26
+ arpeggiate: nil, # true / up / down
27
+
28
+ tied: nil, # start / stop / continue
29
+ tuplet: nil, # Tuplet class instance
30
+
31
+ dynamics: nil, # pppp...ffff (single or array of)
32
+ fermata: nil, # true / upright / inverted
33
+ glissando: nil, # start / stop
34
+ non_arpeggiate: nil, # top / bottom
35
+
36
+ slide: nil, # start / stop
37
+ slur: nil, # start / stop / continue
38
+
39
+ ## articulations
40
+ accent: nil, # true
41
+ breath_mark: nil, # comma / tick
42
+ caesura: nil, # true
43
+ detached_legato:nil, # true
44
+ doit: nil, # true
45
+ falloff: nil, # true
46
+ other_articulation: nil, # text
47
+ plop: nil, # true
48
+ scoop: nil, # true
49
+ spiccato: nil, # true
50
+ staccatissimo: nil, # true
51
+ staccato: nil, # true
52
+ stress: nil, # true
53
+ strong_accent: nil, # true / up / down
54
+ tenuto: nil, # true
55
+ unstress: nil, # true
56
+
57
+ ## ornaments
58
+ delayed_inverted_turn: nil, # true
59
+ delayed_turn: nil, # true
60
+ inverted_mordent: nil, # true
61
+ inverted_turn: nil, # true
62
+ mordent: nil, # true
63
+ schleifer: nil, # true
64
+ shake: nil, # true
65
+ tremolo: nil, # start / stop / single,
66
+ trill_mark: nil, # true
67
+ turn: nil, # true
68
+ vertical_turn: nil, # true
69
+ wavy_line: nil, # true
70
+ other_ornament: nil, # true
71
+ ornament_accidental_mark: nil, # sharp / natural / flat / ...
72
+
73
+ ## technical
74
+ arrow: nil, # Arrow class instance
75
+ bend: nil, # Bend class instance
76
+ double_tongue: nil, # true
77
+ down_bow: nil, # true
78
+ fingering: nil, # Fingering class instance
79
+ fingernails: nil, # true
80
+ fret: nil, # number
81
+ hammer_on: nil, # HammerOnPullOff class instance
82
+ handbell: nil, # damp / echo / ...
83
+ harmonic: nil, # Harmonic class instance
84
+ heel: nil, # true
85
+ hole: nil, # Hole class instance
86
+ open_string: nil, # true
87
+ other_technical: nil, # text
88
+ pluck: nil, # text
89
+ pull_off: nil, # HammerOnPullOff class insstance
90
+ snap_pizzicato: nil, # true
91
+ stopped: nil, # true
92
+ string: nil, # number (string number)
93
+ tap: nil, # text
94
+ thumb_position: nil, # true
95
+ toe: nil, # true
96
+ triple_tongue: nil, # true
97
+ up_bow: nil, # true
98
+ &block)
99
+
100
+ @measure = measure
101
+
102
+ super
103
+ end
104
+
105
+ attr_simple_builder :measure
106
+
107
+ private
108
+
109
+ def specific_to_xml(io, indent:)
110
+ tabs = "\t" * indent
111
+ io.puts "#{tabs}<rest #{"measure=\"yes\"" if @measure}/>"
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,120 @@
1
+ require 'date'
2
+
3
+ require_relative '../../core-ext/attribute-builder'
4
+ require_relative '../../core-ext/with'
5
+
6
+ require_relative 'typed-text'
7
+ require_relative 'part-group'
8
+ require_relative 'part'
9
+
10
+ require_relative 'helper'
11
+
12
+ module Musa
13
+ module MusicXML
14
+ module Builder
15
+ class ScorePartwise
16
+ extend Musa::Extension::AttributeBuilder
17
+ include Musa::Extension::With
18
+
19
+ include Internal::Helper::ToXML
20
+
21
+ def initialize(work_number: nil, work_title: nil,
22
+ movement_number: nil, movement_title: nil,
23
+ encoding_date: nil,
24
+ creators: nil,
25
+ rights: nil,
26
+ &block)
27
+
28
+ @work_number = work_number
29
+ @work_title = work_title
30
+ @movement_number = movement_number
31
+ @movement_title = movement_title
32
+
33
+ @encoding_date = encoding_date || DateTime.now
34
+
35
+ @creators = []
36
+ @rights = []
37
+
38
+ self.creators **creators if creators
39
+ self.rights **rights if rights
40
+
41
+ @groups_and_parts = []
42
+ @parts = {}
43
+
44
+ with &block if block_given?
45
+ end
46
+
47
+ attr_simple_builder :work_title
48
+ attr_simple_builder :work_number
49
+
50
+ attr_simple_builder :movement_title
51
+ attr_simple_builder :movement_number
52
+
53
+ attr_simple_builder :encoding_date
54
+
55
+ attr_tuple_adder_to_array :rights, Internal::Rights, plural: :rights
56
+ attr_tuple_adder_to_array :creator, Internal::Creator
57
+
58
+ attr_complex_adder_to_custom :part, variable: :@parts do |id, name:, abbreviation: nil, &block|
59
+ Internal::Part.new(id, name: name, abbreviation: abbreviation, &block).tap do |part|
60
+ @parts[id] = part
61
+ @groups_and_parts << part
62
+ end
63
+ end
64
+
65
+ attr_complex_adder_to_custom :group do |*parameters, **key_parameters|
66
+ Internal::PartGroup.new(*parameters, **key_parameters).tap do |group|
67
+ @groups_and_parts << group
68
+ end
69
+ end
70
+
71
+ def _to_xml(io, indent:, tabs:)
72
+ io.puts "#{tabs}<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
73
+ io.puts "#{tabs}<!DOCTYPE score-partwise PUBLIC \"-//Recordare//DTD MusicXML 3.0 Partwise//EN\" \"http://www.musicxml.org/dtds/partwise.dtd\">"
74
+ io.puts "#{tabs}<score-partwise version=\"3.0\">"
75
+
76
+ if @work_number || @work_title
77
+ io.puts"#{tabs}\t<work>"
78
+ io.puts"#{tabs}\t\t<work-number>#{@work_number.to_i}</work-number>" if @work_number
79
+ io.puts"#{tabs}\t\t<work-title>#{@work_title}</work-title>" if @work_title
80
+ io.puts"#{tabs}\t</work>"
81
+ end
82
+
83
+ io.puts"#{tabs}\t<movement-number>#{@movement_number.to_i}</movement-number>" if @movement_number
84
+ io.puts"#{tabs}\t<movement-title>#{@movement_title}</movement-title>" if @movement_title
85
+
86
+ io.puts "#{tabs}\t<identification>"
87
+
88
+ @creators.each do |creator|
89
+ creator.to_xml(io, indent: indent + 2)
90
+ end
91
+
92
+ @rights.each do |rights|
93
+ rights.to_xml(io, indent: indent + 2)
94
+ end
95
+
96
+ io.puts "#{tabs}\t\t<encoding>"
97
+ io.puts"#{tabs}\t\t\t<encoding-date>#{@encoding_date.strftime("%Y-%m-%d")}</encoding-date>"
98
+ io.puts"#{tabs}\t\t\t<software>MusaDSL: MusicXML output formatter</software>"
99
+ io.puts "#{tabs}\t\t</encoding>"
100
+
101
+ io.puts "#{tabs}\t</identification>"
102
+
103
+ io.puts "#{tabs}\t<part-list>"
104
+ @groups_and_parts.each do |group_or_part|
105
+ group_or_part.header_to_xml(io, indent: indent + 2)
106
+ end
107
+ io.puts "#{tabs}\t</part-list>"
108
+
109
+ @parts.each_value do |part|
110
+ part.to_xml(io, indent: indent + 1)
111
+ end
112
+
113
+ io.puts "#{tabs}</score-partwise>"
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+