GTP 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c95f11dd3b8984c35d4a5689256f044d63efd63b
4
+ data.tar.gz: 2f350da3f47500d24a2a9467b6f9d004b9dc6a44
5
+ SHA512:
6
+ metadata.gz: f5b9655918545ae36cf5c75948c70e89030226cf52638b1d1905051a1c5adfaba7ab98cee2322a76856e40a7d9f8047a936ef97a214adddb96f2a7a15ff3f680
7
+ data.tar.gz: 14165f6937a8825c3bea4fb3be97a6d660101ed45eeb6d349a72b3999cbb9ca1813e92a543cf69f2c0ff1c6b9e48fbf9379b28f80a4ac64448a1601affc56a91
data/GTP.gemspec CHANGED
@@ -20,4 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'pry'
24
+ spec.add_development_dependency 'json'
23
25
  end
data/lib/GTP.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require "GTP/version"
2
2
  require "GTP/gp4"
3
+ require "GTP/measure"
4
+ require "GTP/io/reader"
3
5
 
4
6
  module GTP
5
-
7
+ def configure(&block)
8
+ block.call self
9
+ end
6
10
  end
data/lib/GTP/gp4.rb CHANGED
@@ -1,117 +1,198 @@
1
+ require "json"
2
+
1
3
  module GTP
2
4
  class GP4
5
+ FIELDS = %w(title subtitle artist album author copyright tab instruction notice triplet_feel)
6
+
7
+ attr_accessor :file, :version, :offset, :lyrics, :tempo, :key, :octave, :num_measures, :num_tracks, :measures
8
+
9
+ attr_accessor *FIELDS
3
10
 
4
- attr_accessor :file,
5
- :version,
6
- :title,
7
- :subtitle,
8
- :artist,
9
- :album,
10
- :author,
11
- :copyright,
12
- :tab,
13
- :instruction,
14
- :notice,
15
- :triplet_feel,
16
- :offset
17
11
  attr_reader :file_path
18
12
 
19
13
  INTEGER_SIZE = 4
20
14
 
21
15
  def initialize(tab_path)
16
+ @reader = Reader.new tab_path
22
17
  @file = File.open(tab_path, "r")
23
- @offset = 31
24
18
  end
25
19
 
26
- def read_string
27
-
28
- self.offset = self.offset+INTEGER_SIZE
20
+ def call
21
+ parse_version
22
+ parse_info
23
+ parse_lyrics
24
+ end
29
25
 
30
- length = IO.binread(self.file, 1, self.offset).bytes.to_a[0].to_i
26
+ def fix_header header
31
27
 
32
- self.offset = self.offset + 1
28
+ counter = 0
33
29
 
34
- string = IO.binread(self.file, length, self.offset)
30
+ new_header = header.reverse
35
31
 
36
- self.offset = self.offset + length
32
+ while 8 > new_header.size
33
+ new_header << "0"
34
+ end
37
35
 
38
- return string
36
+ return new_header
39
37
  end
40
38
 
41
39
  def parse_version
42
-
43
- size = IO.binread(self.file, 1).bytes.to_a[0].to_i
44
-
45
- self.version = IO.binread(self.file, size, 1).strip
40
+ self.version = @reader.read_string
46
41
  end
47
42
 
48
43
  def parse_info
49
- parse_title
50
- parse_subtitle
51
- parse_artist
52
- parse_album
53
- parse_author
54
- parse_copyright
55
- parse_tab
56
- parse_instruction
57
- parse_notice
58
- parse_triplet_feel
44
+ FIELDS.each do |field|
45
+ self.public_send "parse_#{field}"
46
+ end
59
47
  end
60
48
 
61
- def parse_title
62
- self.title = read_string
49
+ FIELDS.each do |field|
50
+ define_method "parse_#{field}" do
51
+ self.public_send "#{field}=", @reader.read_default_string
52
+ end
63
53
  end
64
54
 
65
- def parse_subtitle
66
- self.subtitle = read_string
67
- end
55
+ def parse_notice
56
+ linesCount = @reader.read_integer
68
57
 
69
- def parse_artist
70
- self.artist = read_string
71
- end
58
+ notice = ""
72
59
 
73
- def parse_album
74
- self.album = read_string
75
- end
60
+ linesCount.times do
61
+ notice << @reader.read_default_string << "\n"
62
+ end
76
63
 
77
- def parse_author
78
- self.author = read_string
64
+ self.notice = notice
79
65
  end
80
66
 
81
- def parse_copyright
82
- self.copyright = read_string
67
+ def parse_triplet_feel
68
+ self.triplet_feel = @reader.read_byte.to_s
83
69
  end
84
70
 
85
- def parse_tab
86
- self.tab = read_string
71
+ def parse_lyrics
72
+ track = @reader.read_integer
73
+ self.lyrics = []
74
+
75
+ 5.times do
76
+
77
+ bar = @reader.read_integer
78
+ content = @reader.read_int_string
79
+
80
+ tuple = {}
81
+ tuple.store(bar, content.gsub("\r\n", "\n"))
82
+
83
+ self.lyrics.push(tuple)
84
+ end
87
85
  end
88
86
 
89
- def parse_instruction
90
- self.instruction = read_string
87
+ def parse_tempo
88
+ self.tempo = @reader.read_integer.to_i
91
89
  end
92
90
 
93
- def parse_notice
94
- lines = IO.binread(self.file, INTEGER_SIZE, self.offset).unpack("L")[0]
91
+ def parse_key
92
+ self.key = @reader.read_integer
93
+ end
95
94
 
96
- self.offset = self.offset+INTEGER_SIZE
95
+ def parse_octave
96
+ self.octave = @reader.read_byte
97
+ end
97
98
 
98
- notice = ""
99
+ def parse_midi_channels
100
+ @reader.increment_offset (12 * 16 * 4) # TODO
101
+ end
99
102
 
100
- for i in 1..lines-1
101
- notice << read_string << "\n"
102
- end
103
+ def parse_number_of_measures
104
+ self.num_measures = @reader.read_integer.to_i
105
+ end
103
106
 
104
- notice << read_string
105
-
106
- self.notice = notice
107
+ def parse_number_of_tracks
108
+ self.num_tracks = @reader.read_integer
107
109
  end
108
110
 
109
- def parse_triplet_feel
110
- self.triplet_feel = IO.binread(self.file, 1, self.offset).bytes.to_a[0].to_s
111
+ def parse_measures
112
+
113
+ self.measures = []
114
+
115
+ for n in 1..self.num_measures do
116
+
117
+ header = fix_header read_byte.to_s(2)
118
+ numerator = nil
119
+ denominator = nil
120
+ begin_repeat = nil
121
+ end_repeat = nil
122
+ marker_name = nil
123
+ marker_color = nil
124
+ tonality = nil
125
+ double_bar = nil
126
+
127
+ if header[0] == "1"
128
+ numerator = read_byte
129
+ end
130
+
131
+ if header[1] == "1"
132
+ denominator = read_byte
133
+ end
134
+
135
+ if header[2] == "1"
136
+ begin_repeat = true
137
+ end
138
+
139
+ if header[3] == "1"
140
+ end_repeat = read_byte
141
+ end
142
+
143
+ if header[4] == "1"
144
+ num_alt_ending = read_byte
145
+ end
146
+
147
+ if header[5] == "1"
148
+ marker_name = @reader.read_string
149
+ marker_color = read_integer
150
+ end
151
+
152
+ if header[6] == "1"
153
+ tonality = read_byte
154
+ @reader.increment_offset 1
155
+ end
156
+
157
+ if header[7] == "1"
158
+ double_bar = true
159
+ end
160
+
161
+ measure = Measure.new
162
+ measure.numerator = numerator
163
+ measure.denominator = denominator
164
+ measure.begin_repeat = begin_repeat
165
+ measure.end_repeat = end_repeat
166
+ measure.num_alt_ending = num_alt_ending
167
+ measure.marker_name = marker_name
168
+ measure.marker_color = marker_color
169
+ measure.tonality = tonality
170
+ measure.double_bar = double_bar
171
+
172
+ self.measures.push(measure)
173
+ end
111
174
  end
112
175
 
113
176
  def to_json
114
-
177
+ {
178
+
179
+ "score" => {
180
+
181
+ "info" => {
182
+ "version" => self.version,
183
+ "title" => self.title,
184
+ "subtitle" => self.subtitle,
185
+ "artist" => self.artist,
186
+ "album" => self.album,
187
+ "author" => self.author,
188
+ "copyright" => self.copyright
189
+ },
190
+ "tempo" => self.tempo,
191
+ "key" => self.key,
192
+ "num_track" => self.num_tracks,
193
+ "num_measures" => self.num_measures
194
+ }
195
+ }.to_json
115
196
  end
116
197
  end
117
- end
198
+ end
@@ -0,0 +1,78 @@
1
+ module GTP
2
+ class Reader
3
+
4
+ attr_accessor :offset, :file
5
+ INTEGER_SIZE = 4
6
+
7
+ def initialize(file)
8
+ @file = File.open(file, "r")
9
+ @offset = 0
10
+ end
11
+
12
+ def read_next_chunk_with_offset(size, offset)
13
+ increment_offset size
14
+ IO.binread(self.file, size, offset)
15
+ end
16
+
17
+ def read_integer
18
+ result = IO.binread(self.file, INTEGER_SIZE, self.offset).unpack('L').first
19
+ increment_offset INTEGER_SIZE
20
+ result
21
+ end
22
+
23
+ def increment_offset(delta)
24
+ self.offset = self.offset + delta
25
+ end
26
+
27
+ def read_default_string(amount_to_read=1)
28
+ skip_useless_bytes
29
+ read_next_string amount_to_read
30
+ end
31
+
32
+ def read_string
33
+ value = read_next_string
34
+ skip_bytes value.length
35
+ value
36
+ end
37
+
38
+ def read_first_string_and_unpack
39
+ read_next_string.unpack("L")
40
+ end
41
+
42
+ def read_int_string
43
+ read_next_string INTEGER_SIZE
44
+ end
45
+
46
+ def read_byte
47
+
48
+ result = IO.binread(self.file, 1, self.offset).bytes.to_a
49
+
50
+ increment_offset 1
51
+
52
+ raise "Byte is greather than expected" if result.size > 1
53
+
54
+ result.first.to_i
55
+ end
56
+
57
+ def skip_integer
58
+ increment_offset INTEGER_SIZE
59
+ end
60
+
61
+ protected
62
+ def skip_useless_bytes
63
+ increment_offset INTEGER_SIZE
64
+ end
65
+
66
+ def skip_bytes(size)
67
+ increment_offset 30-size
68
+ end
69
+
70
+ def read_next_string(amount_to_read=1)
71
+ size = IO.binread(self.file, amount_to_read, self.offset).bytes.to_a.first.to_i
72
+ increment_offset amount_to_read
73
+ value = IO.binread(self.file, size, self.offset).strip
74
+ increment_offset size
75
+ value
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,18 @@
1
+ module GTP
2
+ class Measure
3
+ FIELDS = %w(double_bar tonality marker_name marker_color num_alt_ending end_repeat begin_repeat denominator numerator)
4
+ attr_accessor *FIELDS
5
+
6
+ def ==(o)
7
+ o.class == self.class && o.state == state
8
+ end
9
+
10
+ protected
11
+ def state
12
+ info = Array.new
13
+ FIELDS.each do |f|
14
+ info.push(f)
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/GTP/version.rb CHANGED
@@ -1,3 +1,6 @@
1
1
  module GTP
2
- VERSION = "0.0.1"
2
+ MAJOR = 0
3
+ MINOR = 1
4
+ PATCH = 1
5
+ VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}"
3
6
  end
@@ -1,53 +1,119 @@
1
1
  require "test_helper"
2
2
 
3
- describe GTP::GP4 do
3
+ module GTP
4
+ describe GP4 do
4
5
 
5
- it "must read the file version" do
6
- parser = GTP::GP4.new "test/tabs/test.gp4"
6
+ it "must read the file version" do
7
+ parser = GP4.new "test/tabs/test.gp4"
8
+ parser.parse_version
7
9
 
8
- parser.parse_version
10
+ # p parser.version
11
+ parser.version.must_match %r/FICHIER GUITAR PRO v4./
12
+ end
9
13
 
10
- parser.version.must_match %r/FICHIER GUITAR PRO v4./
11
- end
14
+ let(:parser) { GP4.new "test/tabs/test.gp4" }
12
15
 
13
- it "must read the tablature info" do
14
- parser = GTP::GP4.new "test/tabs/test.gp4"
15
-
16
- parser.parse_info
17
-
18
- parser.title.must_equal "Title"
19
- parser.subtitle.must_equal "Subtitle"
20
- parser.artist.must_equal "Artist"
21
- parser.album.must_equal "Album"
22
- parser.author.must_equal "Author"
23
- parser.copyright.must_equal "Copyright"
24
- parser.tab.must_equal "Tab"
25
- parser.instruction.must_equal "Instruction"
26
- parser.notice.must_equal "N line 1\nN line 2\nN line 3\nN line 4"
27
- parser.triplet_feel.must_match "0"
28
- end
16
+ before { parser.call }
29
17
 
30
- it "must read the tablature lyrics" do
31
-
32
- end
18
+ describe 'tablature info' do
19
+ it "must read the tablature info" do
20
+ parser.title.must_equal "Title"
21
+ parser.subtitle.must_equal "Subtitle"
22
+ parser.artist.must_equal "Artist"
23
+ parser.album.must_equal "Album"
24
+ parser.author.must_equal "Author"
25
+ parser.copyright.must_equal "Copyright"
26
+ parser.tab.must_equal "Tab"
27
+ parser.instruction.must_equal "Instruction"
28
+ parser.notice.must_equal "N line 1\nN line 2\nN line 3\nN line 4\n"
29
+ parser.triplet_feel.must_match "0"
30
+ end
31
+ end
33
32
 
34
- it "must read the tablature extra info" do
35
-
36
- end
33
+ describe "Lyrics" do
34
+ it "must read the tablature lyrics" do
35
+ parser.lyrics.must_equal [
36
+ {1=>"1111\n1111\n1111\n1111"},
37
+ {2=>"2222\n2222\n2222\n2222"},
38
+ {1=>"3333\n3333\n3333"},
39
+ {2=>"4444\n4444"},
40
+ {1=>"5555"}
41
+ ]
42
+ end
43
+ end
37
44
 
38
- it "must read the tablature measures" do
39
-
40
- end
45
+ describe "Other information" do
46
+ it "about the piece" do
47
+ parser.parse_tempo
48
+ parser.parse_key
49
+ parser.parse_octave
50
+ parser.parse_midi_channels # <----- PARSE ME PLEASE!!!
51
+ parser.parse_number_of_measures
52
+ parser.parse_number_of_tracks
41
53
 
42
- it "must read the tablature tracks" do
43
-
44
- end
54
+ parser.tempo.must_equal 120
55
+ parser.key.must_equal 1
56
+ parser.octave.must_equal 0
57
+ # parser.midi_channels
58
+ parser.num_measures.must_equal 2
59
+ parser.num_tracks.must_equal 1
60
+ end
61
+ end
45
62
 
46
- it "must read the tablature song" do
47
-
48
- end
63
+ describe "Serialization" do
64
+ it "must serialize as json" do
65
+ parser.to_json.must_equal "{\"score\":{\"info\":{\"version\":\"FICHIER GUITAR PRO v4.06\",\"title\":\"Title\",\"subtitle\":\"Subtitle\",\"artist\":\"Artist\",\"album\":\"Album\",\"author\":\"Author\",\"copyright\":\"Copyright\"},\"tempo\":null,\"key\":null,\"num_track\":null,\"num_measures\":null}}"
66
+ end
67
+ end
68
+
69
+ # describe "Measures" do
70
+ # first_measure = Measure.new
71
+ # second_measure = Measure.new
72
+
73
+ # before do
74
+ # parser.parse_version
75
+ # parser.parse_info
76
+ # parser.parse_lyrics
77
+ # parser.parse_tempo
78
+ # parser.parse_key
79
+ # parser.parse_octave
80
+ # parser.parse_midi_channels
81
+ # parser.parse_number_of_measures
82
+ # parser.parse_number_of_tracks
83
+
84
+ # first_measure.numerator = 4
85
+ # first_measure.denominator = 4
86
+ # first_measure.begin_repeat = true
87
+ # first_measure.end_repeat = nil
88
+ # first_measure.num_alt_ending = nil
89
+ # first_measure.marker_name = nil
90
+ # first_measure.marker_color = nil
91
+ # first_measure.tonality = 1
92
+ # first_measure.double_bar = nil
93
+
94
+ # second_measure.numerator = 7
95
+ # second_measure.denominator = 8
96
+ # second_measure.begin_repeat = nil
97
+ # second_measure.end_repeat = nil
98
+ # second_measure.num_alt_ending = nil
99
+ # second_measure.marker_name = nil
100
+ # second_measure.marker_color = nil
101
+ # second_measure.tonality = nil
102
+ # second_measure.double_bar = nil
103
+
104
+ # end
105
+
106
+ # it "must get the tab measures" do
107
+ # parser.parse_measures
108
+
109
+ # expected_measures = Array.new
110
+ # expected_measures.push(first_measure)
111
+ # expected_measures.push(second_measure)
112
+
113
+ # # require "pry"; binding.pry
49
114
 
50
- it "must read the tablature chord diagrams" do
51
-
115
+ # parser.measures.must_equal expected_measures
116
+ # end
117
+ # end
52
118
  end
53
- end
119
+ end
@@ -0,0 +1,21 @@
1
+ require "test_helper"
2
+
3
+ module GTP
4
+ describe Measure do
5
+
6
+ it "must setup its attributes properly" do
7
+ # measures = Measure.new "11100010"
8
+
9
+ # measures.header.must_equal
10
+ # measures.double_bar.must_equal false
11
+ # measures.tonality.must_equal
12
+ # measures.marker.must_equal false
13
+ # measures.num_alt_ending.must_equal false
14
+ # measures.end_repeat.must_equal false
15
+ # measures.begin_repeat.must_equal true
16
+ # measures.den_key.must_equal 4
17
+ # measures.num_key.must_equal 4
18
+
19
+ end
20
+ end
21
+ end
metadata CHANGED
@@ -1,57 +1,78 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: GTP
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Thiago Rocha
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2013-06-30 00:00:00 -03:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2013-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: bundler
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
25
17
  - - ~>
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 1
29
- - 3
30
- version: "1.3"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
31
20
  type: :development
32
- version_requirements: *id001
33
- - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
34
28
  name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
35
49
  prerelease: false
36
- requirement: &id002 !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- segments:
41
- - 0
42
- version: "0"
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
43
62
  type: :development
44
- version_requirements: *id002
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
45
69
  description: A Guitar Pro file parser
46
- email:
70
+ email:
47
71
  - kimo@kimo.io
48
72
  executables: []
49
-
50
73
  extensions: []
51
-
52
74
  extra_rdoc_files: []
53
-
54
- files:
75
+ files:
55
76
  - .gitignore
56
77
  - GTP.gemspec
57
78
  - Gemfile
@@ -60,46 +81,44 @@ files:
60
81
  - Rakefile
61
82
  - lib/GTP.rb
62
83
  - lib/GTP/gp4.rb
84
+ - lib/GTP/io/reader.rb
85
+ - lib/GTP/measure.rb
63
86
  - lib/GTP/version.rb
64
87
  - test/lib/GTP/gp4_test.rb
88
+ - test/lib/GTP/measure_test.rb
65
89
  - test/lib/GTP/version_test.rb
66
90
  - test/tabs/test.gp3
67
91
  - test/tabs/test.gp4
68
92
  - test/tabs/test.gp5
69
93
  - test/tabs/test2.gp4
70
94
  - test/test_helper.rb
71
- has_rdoc: true
72
- homepage: ""
73
- licenses:
95
+ homepage: ''
96
+ licenses:
74
97
  - MIT
98
+ metadata: {}
75
99
  post_install_message:
76
100
  rdoc_options: []
77
-
78
- require_paths:
101
+ require_paths:
79
102
  - lib
80
- required_ruby_version: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- segments:
85
- - 0
86
- version: "0"
87
- required_rubygems_version: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- segments:
92
- - 0
93
- version: "0"
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
94
113
  requirements: []
95
-
96
114
  rubyforge_project:
97
- rubygems_version: 1.3.6
115
+ rubygems_version: 2.0.3
98
116
  signing_key:
99
- specification_version: 3
117
+ specification_version: 4
100
118
  summary: It parses gtp files
101
- test_files:
119
+ test_files:
102
120
  - test/lib/GTP/gp4_test.rb
121
+ - test/lib/GTP/measure_test.rb
103
122
  - test/lib/GTP/version_test.rb
104
123
  - test/tabs/test.gp3
105
124
  - test/tabs/test.gp4