musicxml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rubocop.yml +25 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +42 -0
  8. data/Rakefile +10 -0
  9. data/bin/console +10 -0
  10. data/lib/musicxml.rb +12 -0
  11. data/lib/musicxml/key_signature.rb +16 -0
  12. data/lib/musicxml/node.rb +129 -0
  13. data/lib/musicxml/node/base.rb +30 -0
  14. data/lib/musicxml/node/config.rb +48 -0
  15. data/lib/musicxml/node/json_export.rb +54 -0
  16. data/lib/musicxml/node/parser.rb +66 -0
  17. data/lib/musicxml/parser.rb +22 -0
  18. data/lib/musicxml/version.rb +3 -0
  19. data/musicxml.gemspec +25 -0
  20. data/samples/ActorPreludeSample.mxl +0 -0
  21. data/samples/ActorPreludeSample.pdf +0 -0
  22. data/samples/ActorPreludeSample.xml +44672 -0
  23. data/samples/BeetAnGeSample.mxl +0 -0
  24. data/samples/BeetAnGeSample.pdf +0 -0
  25. data/samples/BeetAnGeSample.xml +4274 -0
  26. data/samples/Binchois.mxl +0 -0
  27. data/samples/Binchois.png +0 -0
  28. data/samples/Binchois.xml +2547 -0
  29. data/samples/BrahWiMeSample.mxl +0 -0
  30. data/samples/BrahWiMeSample.pdf +0 -0
  31. data/samples/BrahWiMeSample.xml +3023 -0
  32. data/samples/BrookeWestSample.mxl +0 -0
  33. data/samples/BrookeWestSample.pdf +0 -0
  34. data/samples/BrookeWestSample.xml +5940 -0
  35. data/samples/Chant.mxl +0 -0
  36. data/samples/Chant.png +0 -0
  37. data/samples/Chant.xml +482 -0
  38. data/samples/DebuMandSample.mxl +0 -0
  39. data/samples/DebuMandSample.pdf +0 -0
  40. data/samples/DebuMandSample.xml +4201 -0
  41. data/samples/Dichterliebe01.mxl +0 -0
  42. data/samples/Dichterliebe01.pdf +0 -0
  43. data/samples/Dichterliebe01.xml +7607 -0
  44. data/samples/Echigo-Jishi.mxl +0 -0
  45. data/samples/Echigo-Jishi.pdf +0 -0
  46. data/samples/Echigo-Jishi.xml +2559 -0
  47. data/samples/FaurReveSample.mxl +0 -0
  48. data/samples/FaurReveSample.pdf +0 -0
  49. data/samples/FaurReveSample.xml +5667 -0
  50. data/samples/MahlFaGe4Sample.mxl +0 -0
  51. data/samples/MahlFaGe4Sample.pdf +0 -0
  52. data/samples/MahlFaGe4Sample.xml +4876 -0
  53. data/samples/MozaChloSample.mxl +0 -0
  54. data/samples/MozaChloSample.pdf +0 -0
  55. data/samples/MozaChloSample.xml +0 -0
  56. data/samples/MozaVeilSample.mxl +0 -0
  57. data/samples/MozaVeilSample.pdf +0 -0
  58. data/samples/MozaVeilSample.xml +0 -0
  59. data/samples/MozartPianoSonata.mxl +0 -0
  60. data/samples/MozartPianoSonata.png +0 -0
  61. data/samples/MozartPianoSonata.xml +1136 -0
  62. data/samples/MozartTrio.mxl +0 -0
  63. data/samples/MozartTrio.png +0 -0
  64. data/samples/MozartTrio.xml +3498 -0
  65. data/samples/Saltarello.ly +7 -0
  66. data/samples/Saltarello.mxl +0 -0
  67. data/samples/Saltarello.png +0 -0
  68. data/samples/Saltarello.xml +1551 -0
  69. data/samples/SchbAvMaSample.mxl +0 -0
  70. data/samples/SchbAvMaSample.pdf +0 -0
  71. data/samples/SchbAvMaSample.xml +8787 -0
  72. data/samples/Telemann.mxl +0 -0
  73. data/samples/Telemann.png +0 -0
  74. data/samples/Telemann.xml +5498 -0
  75. metadata +187 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e6ee424ff81a6fc3e48e995744f296e7a8796778
4
+ data.tar.gz: ec5671b612320f2cc717dde7f98bcffce3996078
5
+ SHA512:
6
+ metadata.gz: 705281df74f15b612922ab47af95f052221fed252805e06231a65a736310158f5f081045000100d46ea7ce4790ef8bcde20d0f55c5a8bef5dd35df9f7e19cb3e
7
+ data.tar.gz: 20973e13ddcbc7fc6d1bb8b79c951eace6fc58fb8586bf2a50ba62c227b94e472311ed36ba913d5080c3108d9718b2eff5b8e2813c35e3658c3f2c305a6cc641
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ /.bundle/
2
+ /.ruby-version
3
+ /.ruby-gemset
4
+ /coverage/
5
+ /Gemfile.lock
6
+ /pkg/
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+ DisplayStyleGuide: true
4
+ Exclude:
5
+ - vendor/**/*
6
+
7
+ Metrics/LineLength:
8
+ Max: 100
9
+
10
+ Style/Documentation:
11
+ Enabled: false
12
+
13
+ Style/EmptyLinesAroundClassBody:
14
+ Enabled: false
15
+
16
+ Style/EmptyLinesAroundModuleBody:
17
+ Enabled: false
18
+
19
+ Style/PercentLiteralDelimiters:
20
+ PreferredDelimiters:
21
+ '%i': '[]'
22
+ '%w': '[]'
23
+
24
+ Style/PerlBackrefs:
25
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm: 2.3.1
3
+ cache: bundler
4
+ script:
5
+ - bundle exec rake
6
+ - bundle exec rubocop
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Kevin Deisz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # MusicXML
2
+
3
+ [![Build Status](https://travis-ci.org/kddeisz/musicxml.svg?branch=master)](https://travis-ci.org/kddeisz/musicxml)
4
+
5
+ Ruby bindings for MusicXML.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'musicxml'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install musicxml
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ filepath = 'my-piece.xml'
27
+ score = MusicXML::Parser.new(filepath)
28
+ ```
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
35
+
36
+ ## Contributing
37
+
38
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kddeisz/musicxml.
39
+
40
+ ## License
41
+
42
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'musicxml'
5
+
6
+ filepath = ARGV.shift
7
+ @score = MusicXML::Parser.new(filepath).parse if filepath
8
+
9
+ require 'irb'
10
+ IRB.start
data/lib/musicxml.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'forwardable'
2
+ require 'json'
3
+ require 'nokogiri'
4
+
5
+ require 'musicxml/node/config'
6
+ require 'musicxml/node/json_export'
7
+ require 'musicxml/node/base'
8
+ require 'musicxml/node/parser'
9
+ require 'musicxml/node'
10
+
11
+ require 'musicxml/key_signature'
12
+ require 'musicxml/parser'
@@ -0,0 +1,16 @@
1
+ module MusicXML
2
+ class KeySignature
3
+
4
+ FIFTHS = %w[Gb Db Ab Eb Bb F C G D A E B F#].freeze
5
+
6
+ attr_reader :number
7
+
8
+ def initialize(number)
9
+ @number = number
10
+ end
11
+
12
+ def humanize
13
+ FIFTHS[number + 6]
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,129 @@
1
+ module MusicXML
2
+ # Namespace for all nodes defined by the system. Nodes are used
3
+ # to represent the various segments of the XML describing different
4
+ # musical concepts.
5
+ module Node
6
+
7
+ class << self
8
+ attr_accessor :registry
9
+ end
10
+ self.registry = {}
11
+
12
+ def self.register(name, &block)
13
+ class_name = name.to_s.capitalize.gsub(/\_([a-z])/) { $1.to_s.upcase }
14
+ clazz = Class.new(Base, &block)
15
+
16
+ registry[name] = clazz
17
+ const_set(class_name.to_sym, clazz)
18
+ end
19
+
20
+ register :articulations do
21
+ sattrs :accent, :breath_mark, :staccato, :tenuto
22
+ end
23
+
24
+ register :attributes do
25
+ pattrs :divisions, :staves
26
+ snodes :clef, :key, :transpose
27
+ end
28
+
29
+ register :barline do
30
+ snodes :repeat
31
+ end
32
+
33
+ register :chord
34
+
35
+ register :clef do
36
+ sattrs :line, :sign
37
+ end
38
+
39
+ register :defaults do
40
+ sattrs :music_font, :word_font
41
+ end
42
+
43
+ register :direction do
44
+ snodes :direction_type
45
+ end
46
+
47
+ register :direction_type do
48
+ pattrs :words, :dynamics
49
+ end
50
+
51
+ register :dot
52
+
53
+ register :encoding do
54
+ pattrs :supports
55
+ sattrs :encoding_data, :software
56
+ end
57
+
58
+ register :identification do
59
+ sattrs :creator, :rights
60
+ snodes :encoding
61
+ end
62
+
63
+ register :key do
64
+ sattrs :fifths, :mode
65
+
66
+ def humanize
67
+ (@key_signature ||= KeySignature.new(fifths.to_i)).humanize
68
+ end
69
+ end
70
+
71
+ register :measure do
72
+ sattrs :sound
73
+ snodes :clef, :direction, :key, :time, :barline, :transpose
74
+ pnodes :note
75
+ end
76
+
77
+ register :notations do
78
+ pnodes :articulations
79
+ sattrs :arpeggiate, :slur
80
+ end
81
+
82
+ register :note do
83
+ sattrs :duration, :staff, :stem, :type, :voice, :accidental
84
+
85
+ pnodes :notations, :dot
86
+ snodes :pitch, :chord
87
+ end
88
+
89
+ register :part do
90
+ pnodes :measure
91
+ end
92
+
93
+ register :part_list do
94
+ pnodes :score_part
95
+ end
96
+
97
+ register :pitch do
98
+ sattrs :step, :alter, :octave
99
+ end
100
+
101
+ register :repeat do
102
+ props :direction, :times
103
+ end
104
+
105
+ register :score_instrument do
106
+ sattrs :instrument_name
107
+ end
108
+
109
+ register :score_part do
110
+ sattrs :part_name
111
+ snodes :score_instrument
112
+ end
113
+
114
+ register :score_partwise do
115
+ sattrs :movement_title
116
+
117
+ pnodes :defaults, :part
118
+ snodes :identification, :part_list
119
+ end
120
+
121
+ register :time do
122
+ sattrs :beats, :beat_type
123
+ end
124
+
125
+ register :transpose do
126
+ sattrs :diatonic, :chromatic, :octave
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,30 @@
1
+ module MusicXML
2
+ module Node
3
+
4
+ # Superclass for all node types
5
+ class Base
6
+
7
+ include JsonExport
8
+
9
+ # Build a Parser to parse the node based on this class' config
10
+ def initialize(node)
11
+ Parser.new(node: node, config: self.class.config).parse.each do |key, value|
12
+ instance_variable_set(key, value)
13
+ end
14
+ end
15
+
16
+ class << self
17
+ # forward class methods to the config to store the configuration
18
+ extend Forwardable
19
+ def_delegators :config, :pattrs, :pnodes, :props, :sattrs, :snodes
20
+
21
+ attr_accessor :config
22
+
23
+ # when this class is subclassed build a new config
24
+ def inherited(subclass)
25
+ subclass.config = ::MusicXML::Node::Config.new(subclass)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ module MusicXML
2
+ module Node
3
+ class Config
4
+
5
+ attr_accessor :clazz, :properties
6
+ attr_accessor :plural_attrs, :singular_attrs
7
+ attr_accessor :plural_nodes, :singular_nodes
8
+
9
+ def initialize(clazz)
10
+ self.clazz = clazz
11
+ %w[plural_attrs plural_nodes singular_attrs singular_nodes properties].each do |name|
12
+ send("#{name}=", [])
13
+ end
14
+ end
15
+
16
+ def pattrs(*names)
17
+ self.plural_attrs += names
18
+ add_accessors(*names)
19
+ end
20
+
21
+ def pnodes(*names)
22
+ self.plural_nodes += names
23
+ add_accessors(*names)
24
+ end
25
+
26
+ def props(*names)
27
+ self.properties += names
28
+ add_accessors(*names)
29
+ end
30
+
31
+ def sattrs(*names)
32
+ self.singular_attrs += names
33
+ add_accessors(*names)
34
+ end
35
+
36
+ def snodes(*names)
37
+ self.singular_nodes += names
38
+ add_accessors(*names)
39
+ end
40
+
41
+ private
42
+
43
+ def add_accessors(*names)
44
+ clazz.class_eval { attr_accessor(*names) }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,54 @@
1
+ module MusicXML
2
+ module Node
3
+ module JsonExport
4
+ def to_json
5
+ { json_key => json_values }.to_json
6
+ end
7
+
8
+ def json_key
9
+ self.class.name.split('::').last.gsub(/^([A-Z])/) { $1.downcase }
10
+ end
11
+
12
+ def json_values
13
+ output = {}
14
+ load_plural_attrs(output)
15
+ load_singular_attrs(output)
16
+ load_plural_nodes(output)
17
+ load_singular_nodes(output)
18
+ output
19
+ end
20
+
21
+ private
22
+
23
+ def jsify(name)
24
+ name.to_s.gsub(/(_[a-z])/) { $1.upcase[1..-1] }
25
+ end
26
+
27
+ def load_plural_attrs(output)
28
+ self.class.config.plural_attrs.each do |name|
29
+ output[jsify(name)] = send(name) || []
30
+ end
31
+ end
32
+
33
+ def load_plural_nodes(output)
34
+ self.class.config.plural_nodes.each do |name|
35
+ nodes = send(name)
36
+ output[jsify(name)] = nodes ? nodes.map(&:json_values) : []
37
+ end
38
+ end
39
+
40
+ def load_singular_attrs(output)
41
+ (self.class.config.properties + self.class.config.singular_attrs).each do |name|
42
+ output[jsify(name)] = send(name)
43
+ end
44
+ end
45
+
46
+ def load_singular_nodes(output)
47
+ self.class.config.singular_nodes.each do |name|
48
+ node = send(name)
49
+ output[jsify(name)] = node ? node.json_values : nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end