midi-message 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,21 +1,22 @@
1
- #!/usr/bin/env ruby
2
- #
3
-
4
1
  module MIDIMessage
5
2
 
6
- # common behavior amongst all Message types
3
+ # Common behavior amongst all Message types
7
4
  module ShortMessage
8
5
 
9
6
  attr_reader :name,
10
7
  :status,
11
8
  :verbose_name
12
-
9
+
10
+ # Initialize the message status
11
+ # @param [Fixnum] status_nibble_1 The first nibble of the status
12
+ # @param [Fixnum] status_nibble_2 The second nibble of the status
13
13
  def initialize_short_message(status_nibble_1, status_nibble_2)
14
14
  @status = [status_nibble_1, status_nibble_2]
15
15
  populate_using_const
16
16
  end
17
17
 
18
- # byte array representation of the object eg [0x90, 0x40, 0x40] for NoteOn(0x40, 0x40)
18
+ # Byte array representation of the message eg [0x90, 0x40, 0x40] for NoteOn(0x40, 0x40)
19
+ # @return [Array<Fixnum>] The array of bytes in the MIDI message
19
20
  def to_a
20
21
  data = @data.nil? ? [] : [@data[0], @data[1]]
21
22
  [(@status[0] << 4) + @status[1], *data].compact
@@ -24,7 +25,8 @@ module MIDIMessage
24
25
  alias_method :to_byte_array, :to_a
25
26
  alias_method :to_bytes, :to_a
26
27
 
27
- # string representation of the object's bytes eg "904040" for NoteOn(0x40, 0x40)
28
+ # String representation of the message's bytes eg "904040" for NoteOn(0x40, 0x40)
29
+ # @return [String] The bytes of the message as a string of hex bytes
28
30
  def to_hex_s
29
31
  TypeConversion.numeric_byte_array_to_hex_string(to_a)
30
32
  end
@@ -42,16 +44,16 @@ module MIDIMessage
42
44
 
43
45
  private
44
46
 
45
- # this will populate message metadata with information gathered from midi.yml
47
+ # This will populate message metadata with information gathered from midi.yml
46
48
  def populate_using_const
47
49
  const_group_name = self.class.display_name
48
- group_name_alias = self.class.constants
49
- prop = self.class.map_constants_to
50
- val = self.send(prop) unless prop.nil?
51
- val ||= @status[1] # default property to use for constants
50
+ group_name_alias = self.class.constant_name
51
+ property = self.class.constant_property
52
+ value = self.send(property) unless property.nil?
53
+ value ||= @status[1] # default property to use for constants
52
54
  group = ConstantGroup[group_name_alias] || ConstantGroup[const_group_name]
53
55
  unless group.nil?
54
- const = group.find_by_value(val)
56
+ const = group.find_by_value(value)
55
57
  unless const.nil?
56
58
  @const = const
57
59
  @name = @const.nil? ? const.key : @const.key
@@ -61,38 +63,50 @@ module MIDIMessage
61
63
  end
62
64
 
63
65
  module ClassMethods
64
-
65
- attr_reader :display_name, :constants, :map_constants_to
66
-
66
+
67
+ # Find a constant value in this class's group for the passed in key
68
+ # @param [String] name The constant key
69
+ # @return [String] The constant value
67
70
  def get_constant(name)
68
- key = @constants || @display_name
71
+ key = constant_name || display_name
69
72
  unless key.nil?
70
73
  group = ConstantGroup[key]
71
74
  group.find(name)
72
75
  end
73
76
  end
74
77
 
75
- # this returns a builder for the class, preloaded with the selected const
76
- def [](const_name)
77
- const = get_constant(const_name)
78
- MessageBuilder.new(self, const) unless const.nil?
78
+ def display_name
79
+ const_get("DISPLAY_NAME") if const_defined?("DISPLAY_NAME")
79
80
  end
80
-
81
- def use_display_name(name)
82
- @display_name = name
81
+
82
+ def constant_map
83
+ const_get("CONSTANT") if const_defined?("CONSTANT")
83
84
  end
84
85
 
85
- def use_constants(name, options = {})
86
- @map_constants_to = options[:for]
87
- @constants = name
86
+ def constant_name
87
+ constant_map.keys.first unless constant_map.nil?
88
88
  end
89
89
 
90
+ def constant_property
91
+ constant_map[constant_name] unless constant_map.nil?
92
+ end
93
+
94
+ # This returns a MessageBuilder for the class, preloaded with the selected const
95
+ # @param [String, Symbol] const_name The constant key to use to build the message
96
+ # @return [MIDIMessage::MessageBuilder] A MessageBuilder object for the passed in constant
97
+ def [](const_name)
98
+ const = get_constant(const_name.to_s)
99
+ MessageBuilder.new(self, const) unless const.nil?
100
+ end
101
+
90
102
  end
91
103
 
92
104
  end
93
105
 
94
106
  class MessageBuilder
95
107
 
108
+ # @param [MIDIMessage] klass The message class to build
109
+ # @param [String] const The constant to build the message with
96
110
  def initialize(klass, const)
97
111
  @klass = klass
98
112
  @const = const
@@ -105,10 +119,12 @@ module MIDIMessage
105
119
 
106
120
  end
107
121
 
108
- # shortcuts for dealing with message status
122
+ # Shortcuts for dealing with message status
109
123
  module Status
110
124
 
111
- # this returns the value of the Status constant with the name status_name
125
+ # The value of the Status constant with the name status_name
126
+ # @param [String] status_name The key to use to look up a constant value
127
+ # @return [String] The constant value that was looked up
112
128
  def self.[](status_name)
113
129
  const = Constant.find("Status", status_name)
114
130
  const.value unless const.nil?
@@ -1,21 +1,17 @@
1
- #!/usr/bin/env ruby
2
- #
3
-
4
1
  module MIDIMessage
5
2
 
6
3
  # MIDI System-Exclusive Messages (SysEx)
7
4
  module SystemExclusive
8
5
 
9
- # basic SysEx data that a message class will contain
10
- module Base
6
+ # Common SysEx data that a message class will contain
7
+ module InstanceMethods
11
8
 
12
9
  attr_accessor :node
13
- attr_reader :address,
14
- :checksum
10
+ attr_reader :address, :checksum
15
11
 
16
12
  StartByte = 0xF0
17
13
  EndByte = 0xF7
18
-
14
+
19
15
  # an array of message parts. multiple byte parts will be represented as an array of bytes
20
16
  def to_a(options = {})
21
17
  omit = options[:omit] || []
@@ -40,13 +36,13 @@ module MIDIMessage
40
36
  alias_method :to_byte_array, :to_numeric_byte_array
41
37
  alias_method :to_bytes, :to_numeric_byte_array
42
38
  alias_method :to_byte_a, :to_numeric_byte_array
43
-
39
+
44
40
  # string representation of the object's bytes
45
41
  def to_hex_s
46
42
  to_bytes.map { |b| s = b.to_s(16); s.length.eql?(1) ? "0#{s}" : s }.join.upcase
47
43
  end
48
44
  alias_method :to_bytestr, :to_hex_s
49
-
45
+
50
46
  def name
51
47
  "System Exclusive"
52
48
  end
@@ -55,14 +51,14 @@ module MIDIMessage
55
51
  def type_byte
56
52
  self.class::TypeByte
57
53
  end
58
-
54
+
59
55
  # alternate method from
60
56
  # http://www.2writers.com/eddie/TutSysEx.htm
61
57
  def checksum
62
58
  sum = (address + [value].flatten).inject { |a, b| a + b }
63
59
  (128 - sum.divmod(128)[1])
64
60
  end
65
-
61
+
66
62
  private
67
63
 
68
64
  def initialize_sysex(address, options = {})
@@ -70,79 +66,22 @@ module MIDIMessage
70
66
  @checksum = options[:checksum]
71
67
  @address = address
72
68
  end
73
-
74
- end
75
-
76
- # A SysEx command message
77
- # a command message is identified by having a status byte equal to 0x12
78
- #
79
- class Command
80
69
 
81
- include Base
82
-
83
- attr_accessor :data
84
- alias_method :value, :data
85
- #alias_method :value=, :data=
86
-
87
- TypeByte = 0x12
88
-
89
- def initialize(address, data, options = {})
90
- # store as a byte if it's a single byte
91
- @data = (data.kind_of?(Array) && data.length.eql?(1)) ? data[0] : data
92
- initialize_sysex(address, options)
93
- end
94
-
95
70
  end
96
-
97
- # A SysEx request message
98
- # A request message is identified by having a status byte equal to 0x11
99
- #
100
- class Request
101
-
102
- include Base
103
-
104
- attr_reader :size
105
71
 
106
- alias_method :value, :size
107
-
108
- TypeByte = 0x11
109
-
110
- def initialize(address, size, options = {})
111
- self.size = (size.kind_of?(Array) && size.length.eql?(1)) ? size[0] : size
112
- initialize_sysex(address, options)
113
- end
114
-
115
- def size=(val)
116
- # accepts a Numeric or Array but
117
- # must always store value as an array of three bytes
118
- size = []
119
- if val.kind_of?(Array) && val.size <= 3
120
- size = val
121
- elsif val.kind_of?(Numeric) && (((val + 1) / 247) <= 2)
122
- size = []
123
- div, mod = *val.divmod(247)
124
- size << mod unless mod.zero?
125
- div.times { size << 247 }
126
- end
127
- (3 - size.size).times { size.unshift 0 }
128
- @size = size
129
- end
130
-
131
- end
132
-
133
72
  # A SysEx message with no implied type
134
73
  #
135
74
  class Message
136
75
 
137
- include Base
138
-
76
+ include InstanceMethods
77
+
139
78
  attr_accessor :data
140
-
79
+
141
80
  def initialize(data, options = {})
142
81
  @data = (data.kind_of?(Array) && data.length.eql?(1)) ? data[0] : data
143
82
  initialize_sysex(nil, options)
144
83
  end
145
-
84
+
146
85
  # an array of message parts. multiple byte parts will be represented as an array of bytes
147
86
  def to_a(options = {})
148
87
  omit = options[:omit] || []
@@ -155,7 +94,7 @@ module MIDIMessage
155
94
  self.class::EndByte
156
95
  ].compact
157
96
  end
158
-
97
+
159
98
  end
160
99
 
161
100
  #
@@ -166,13 +105,13 @@ module MIDIMessage
166
105
 
167
106
  attr_accessor :device_id
168
107
  attr_reader :manufacturer_id, :model_id
169
-
108
+
170
109
  def initialize(manufacturer, options = {})
171
110
  @device_id = options[:device_id]
172
111
  @model_id = options[:model_id]
173
112
  @manufacturer_id = manufacturer.kind_of?(Numeric) ? manufacturer : Constant.find("Manufacturer", manufacturer).value
174
113
  end
175
-
114
+
176
115
  def to_a(options = {})
177
116
  omit = options[:omit] || []
178
117
  [
@@ -189,14 +128,14 @@ module MIDIMessage
189
128
  copy.node = self
190
129
  copy
191
130
  end
192
-
131
+
193
132
  # create a new Command message associated with this node
194
133
  def command(*a)
195
134
  command = Command.new(*a)
196
135
  command.node = self
197
136
  command
198
137
  end
199
-
138
+
200
139
  # create a new Request message associated with this node
201
140
  def request(*a)
202
141
  request = Request.new(*a)
@@ -205,40 +144,41 @@ module MIDIMessage
205
144
  end
206
145
 
207
146
  end
208
-
209
- # convert raw MIDI data to SysEx message objects
147
+
148
+ # Convert raw MIDI data to SysEx message objects
210
149
  def self.new(*bytes)
211
150
 
212
151
  start_status = bytes.shift
213
152
  end_status = bytes.pop
214
153
 
215
- return nil unless start_status.eql?(0xF0) && end_status.eql?(0xF7)
216
-
217
- type_byte = bytes[3]
218
-
219
- # if the 4th byte isn't status, we will just make this a Message object -- this may need some tweaking
220
- if type_byte == 0x11
221
- msg_class = Request
222
- elsif type_byte == 0x12
223
- msg_class = Command
224
- else
225
- return Message.new(bytes)
226
- end
227
-
228
- fixed_length_message_part = bytes.slice!(0,7)
154
+ if start_status.eql?(0xF0) && end_status.eql?(0xF7)
229
155
 
230
- manufacturer_id = fixed_length_message_part[0]
231
- device_id = fixed_length_message_part[1]
232
- model_id = fixed_length_message_part[2]
156
+ type_byte = bytes[3]
233
157
 
234
- address = fixed_length_message_part.slice(4,3)
235
- checksum = bytes.slice!((bytes.length - 1), 1)
236
- value = bytes
158
+ # if the 4th byte isn't status, we will just make this a Message object -- this may need some tweaking
159
+ if type_byte == 0x11
160
+ msg_class = Request
161
+ elsif type_byte == 0x12
162
+ msg_class = Command
163
+ else
164
+ return Message.new(bytes)
165
+ end
237
166
 
238
- node = Node.new(manufacturer_id, :model_id => model_id, :device_id => device_id)
239
- msg_class.new(address, value, :checksum => checksum, :node => node)
167
+ fixed_length_message_part = bytes.slice!(0,7)
168
+
169
+ manufacturer_id = fixed_length_message_part[0]
170
+ device_id = fixed_length_message_part[1]
171
+ model_id = fixed_length_message_part[2]
172
+
173
+ address = fixed_length_message_part.slice(4,3)
174
+ checksum = bytes.slice!((bytes.length - 1), 1)
175
+ value = bytes
176
+
177
+ node = Node.new(manufacturer_id, :model_id => model_id, :device_id => device_id)
178
+ msg_class.new(address, value, :checksum => checksum, :node => node)
179
+ end
240
180
  end
241
181
 
242
182
  end
243
183
 
244
- end
184
+ end
@@ -1,67 +1,21 @@
1
- #!/usr/bin/env ruby
2
- #
3
-
4
1
  module MIDIMessage
5
2
 
6
- #
7
- # MIDI System message
8
- #
3
+ # Common MIDI system message behavior
9
4
  module SystemMessage
10
5
 
6
+ def self.included(base)
7
+ base.include(ShortMessage)
8
+ end
9
+
11
10
  # In the case of something like SystemCommon.new(0xF2, 0x00, 0x08), the first nibble F is redundant because
12
11
  # all system messages start with 0xF and it can be assumed.
13
12
  # However, the this method looks to see if this has occurred and strips the redundancy
14
- # @param [Integer] byte The byte to strip of a redundant 0xF
15
- # @return [Integer] The remaining nibble
13
+ # @param [Fixnum] byte The byte to strip of a redundant 0xF
14
+ # @return [Fixnum] The remaining nibble
16
15
  def strip_redundant_nibble(byte)
17
16
  byte > 0xF ? (byte & 0x0F) : byte
18
17
  end
19
18
 
20
19
  end
21
-
22
- #
23
- # MIDI System-Common message
24
- #
25
- class SystemCommon
26
-
27
- include ShortMessage
28
- include SystemMessage
29
- use_display_name 'System Common'
30
-
31
- attr_reader :data
32
-
33
- def initialize(*a)
34
- options = a.last.kind_of?(Hash) ? a.pop : {}
35
- @const = options[:const]
36
- id = @const.nil? ? a.shift : @const.value
37
- id = strip_redundant_nibble(id)
38
- initialize_short_message(0xF, id)
39
- @data = [a[0], a[1]]
40
- end
41
20
 
42
- end
43
-
44
- #
45
- # MIDI System-Realtime message
46
- #
47
- class SystemRealtime
48
-
49
- include ShortMessage
50
- include SystemMessage
51
- use_display_name 'System Realtime'
52
-
53
- def initialize(*a)
54
- options = a.last.kind_of?(Hash) ? a.pop : {}
55
- @const = options[:const]
56
- id = @const.nil? ? a[0] : @const.value
57
- id = strip_redundant_nibble(id)
58
- initialize_short_message(0xF, id)
59
- end
60
-
61
- def id
62
- @status[1]
63
- end
64
-
65
- end
66
-
67
21
  end
@@ -1,11 +1,11 @@
1
- #!/usr/bin/env ruby
2
- #
3
1
  module MIDIMessage
4
2
 
5
- # this is a helper for converting nibbles and bytes
3
+ # Helper for converting nibbles and bytes
6
4
  module TypeConversion
7
5
 
8
- def self.hex_chars_to_numeric_byte_array(nibbles)
6
+ extend self
7
+
8
+ def hex_chars_to_numeric_byte_array(nibbles)
9
9
  nibbles = nibbles.dup
10
10
  # get rid of last nibble if there's an odd number
11
11
  # it will be processed later anyway
@@ -18,8 +18,8 @@ module MIDIMessage
18
18
  bytes
19
19
  end
20
20
 
21
- # convert byte str to byte array
22
- def self.hex_string_to_numeric_byte_array(str)
21
+ # Convert byte str to byte array
22
+ def hex_string_to_numeric_byte_array(str)
23
23
  str = str.dup
24
24
  bytes = []
25
25
  until str.eql?("")
@@ -28,20 +28,20 @@ module MIDIMessage
28
28
  bytes
29
29
  end
30
30
 
31
- # converts a string of hex digits to bytes
32
- def self.hex_str_to_hex_chars(str)
31
+ # Converts a string of hex digits to bytes
32
+ def hex_str_to_hex_chars(str)
33
33
  str.split(//)
34
34
  end
35
35
 
36
- def self.numeric_byte_array_to_hex_string(bytes)
36
+ def numeric_byte_array_to_hex_string(bytes)
37
37
  bytes.map { |b| s = b.to_s(16); s.length.eql?(1) ? "0#{s}" : s }.join.upcase
38
38
  end
39
39
 
40
- def self.numeric_byte_to_hex_chars(num)
40
+ def numeric_byte_to_hex_chars(num)
41
41
  [((num & 0xF0) >> 4), (num & 0x0F)].map { |n| n.to_s(16) }
42
42
  end
43
43
 
44
44
 
45
45
  end
46
46
 
47
- end
47
+ end
data/lib/midi-message.rb CHANGED
@@ -1,40 +1,29 @@
1
- #!/usr/bin/env ruby
2
1
  #
3
- # MIDI Messages in Ruby
4
- # (c)2011 Ari Russo and licensed under the Apache 2.0 License
2
+ # Ruby MIDI message objects
3
+ #
4
+ # (c)2011-2014 Ari Russo and licensed under the Apache 2.0 License
5
5
  #
6
6
  module MIDIMessage
7
-
8
- module Event
9
- end
10
-
11
- module Process
12
- end
13
-
14
- VERSION = "0.3.2"
7
+
8
+ VERSION = "0.4.1"
15
9
 
16
10
  end
17
11
 
18
- # libs
12
+ # Libs
19
13
  require "forwardable"
20
14
  require "yaml"
21
15
 
22
- # messages (mixed format)
16
+ # Modules
23
17
  require "midi-message/short_message"
24
18
  require "midi-message/channel_message"
25
- require "midi-message/constant"
26
- require "midi-message/context"
27
19
  require "midi-message/note_message"
28
- require "midi-message/parser"
29
- require "midi-message/system_message"
30
20
  require "midi-message/system_exclusive"
21
+ require "midi-message/system_message"
31
22
  require "midi-message/type_conversion"
32
23
 
33
- # modules
34
- require "midi-message/process/processor"
24
+ # Classes
25
+ require "midi-message/constant"
26
+ require "midi-message/context"
27
+ require "midi-message/message"
28
+ require "midi-message/parser"
35
29
 
36
- # classes
37
- require "midi-message/event/note"
38
- require "midi-message/process/filter"
39
- require "midi-message/process/limit"
40
- require "midi-message/process/transpose"
File without changes
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,77 +1,66 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: midi-message
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
5
- prerelease:
4
+ version: 0.4.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ari Russo
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-09-17 00:00:00.000000000 Z
11
+ date: 2014-09-01 00:00:00.000000000 Z
13
12
  dependencies: []
14
- description: MIDI messages, objectified in Ruby
13
+ description: Objects and classes for dealing with MIDI messages.
15
14
  email:
16
15
  - ari.russo@gmail.com
17
16
  executables: []
18
17
  extensions: []
19
18
  extra_rdoc_files: []
20
19
  files:
20
+ - LICENSE
21
+ - README.md
22
+ - lib/midi-message.rb
21
23
  - lib/midi-message/channel_message.rb
22
24
  - lib/midi-message/constant.rb
23
25
  - lib/midi-message/context.rb
24
- - lib/midi-message/event/note.rb
26
+ - lib/midi-message/message.rb
25
27
  - lib/midi-message/note_message.rb
26
28
  - lib/midi-message/parser.rb
27
- - lib/midi-message/process/filter.rb
28
- - lib/midi-message/process/limit.rb
29
- - lib/midi-message/process/processor.rb
30
- - lib/midi-message/process/transpose.rb
31
29
  - lib/midi-message/short_message.rb
32
30
  - lib/midi-message/system_exclusive.rb
33
31
  - lib/midi-message/system_message.rb
34
32
  - lib/midi-message/type_conversion.rb
35
- - lib/midi-message.rb
36
33
  - lib/midi.yml
34
+ - test/constants_test.rb
35
+ - test/context_test.rb
37
36
  - test/helper.rb
38
- - test/test_constants.rb
39
- - test/test_context.rb
40
- - test/test_filter.rb
41
- - test/test_limit.rb
42
- - test/test_mutability.rb
43
- - test/test_note_event.rb
44
- - test/test_parser.rb
45
- - test/test_processor.rb
46
- - test/test_short_message.rb
47
- - test/test_system_exclusive.rb
48
- - test/test_system_message.rb
49
- - test/test_transpose.rb
50
- - LICENSE
51
- - README.rdoc
52
- - TODO
37
+ - test/mutability_test.rb
38
+ - test/parser_test.rb
39
+ - test/short_message_test.rb
40
+ - test/system_exclusive_test.rb
41
+ - test/system_message_test.rb
53
42
  homepage: http://github.com/arirusso/midi-message
54
- licenses: []
43
+ licenses:
44
+ - Apache 2.0
45
+ metadata: {}
55
46
  post_install_message:
56
47
  rdoc_options: []
57
48
  require_paths:
58
49
  - lib
59
50
  required_ruby_version: !ruby/object:Gem::Requirement
60
- none: false
61
51
  requirements:
62
- - - ! '>='
52
+ - - ">="
63
53
  - !ruby/object:Gem::Version
64
54
  version: '0'
65
55
  required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
56
  requirements:
68
- - - ! '>='
57
+ - - ">="
69
58
  - !ruby/object:Gem::Version
70
59
  version: 1.3.6
71
60
  requirements: []
72
61
  rubyforge_project: midi-message
73
- rubygems_version: 1.8.23
62
+ rubygems_version: 2.2.2
74
63
  signing_key:
75
- specification_version: 3
76
- summary: MIDI messages, objectified in Ruby
64
+ specification_version: 4
65
+ summary: Ruby MIDI message objects
77
66
  test_files: []