midi-message 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []