ffi-coremidi 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2011 Ari Russo
1
+ Copyright 2011-2013 Ari Russo
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -10,4 +10,4 @@ Unless required by applicable law or agreed to in writing, software
10
10
  distributed under the License is distributed on an "AS IS" BASIS,
11
11
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  See the License for the specific language governing permissions and
13
- limitations under the License.
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # ffi-coremidi
2
+
3
+ #### Realtime MIDI IO with Ruby for OSX
4
+
5
+ This is a Ruby implementation of the Apple Core MIDI framework API.
6
+
7
+ Note that in the interest of allowing people on other platforms to utilize your code, please consider using [UniMIDI](http://github.com/arirusso/unimidi). UniMIDI is a platform independent wrapper which implements this library with a similar API.
8
+
9
+ ### Features
10
+
11
+ * Simpler API than Core MIDI
12
+ * Input and output on multiple devices concurrently
13
+ * Agnostically handle different MIDI Message types (including SysEx)
14
+ * Timestamped input events
15
+ * Internally patch MIDI to other programs using IAC
16
+
17
+ ### Requirements
18
+
19
+ * [ffi](http://github.com/ffi/ffi)
20
+
21
+ ### Install
22
+
23
+ If you're using Bundler, add this line to your application's Gemfile:
24
+
25
+ `gem "ffi-coremidi"`
26
+
27
+ Otherwise
28
+
29
+ `gem install ffi-coremidi`
30
+
31
+ ### Documentation
32
+
33
+ [rdoc](http://rubydoc.info/github/arirusso/ffi-coremidi)
34
+
35
+ ### Author
36
+
37
+ [Ari Russo](http://github.com/arirusso) <ari.russo at gmail.com>
38
+
39
+ ### Credits
40
+
41
+ This library began with some coremidi/ffi binding code for MIDI output by [Colin Harris](http://github.com/aberant) contained in [his fork of MIDIator](http://github.com/aberant/midiator) and a [blog post](http://aberant.tumblr.com/post/694878119/sending-midi-sysex-with-core-midi-and-ruby-ffi).
42
+
43
+ [MIDIator](http://github.com/bleything/midiator) is (c)2008 by Ben Bleything and Topher Cyll and released under the MIT license (see LICENSE.midiator and LICENSE.prp)
44
+
45
+ Also thank you to [Jeremy Voorhis](http://github.com/jvoorhis) for some useful debugging.
46
+
47
+ ### License
48
+
49
+ Apache 2.0, See the file LICENSE
50
+
51
+ Copyright (c) 2011-2013 [Ari Russo](http://github.com/arirusso)
data/lib/coremidi.rb CHANGED
@@ -1,9 +1,6 @@
1
- #!/usr/bin/env ruby
2
- #
3
1
  # ffi-coremidi
4
2
  # Realtime MIDI IO with Ruby for OSX
5
- # (c)2011 Ari Russo
6
- #
3
+ # (c)2011-2013 Ari Russo
7
4
 
8
5
  # libs
9
6
  require 'ffi'
@@ -20,5 +17,5 @@ require 'coremidi/source'
20
17
  require 'coremidi/destination'
21
18
 
22
19
  module CoreMIDI
23
- VERSION = "0.1.8"
20
+ VERSION = "0.2.0"
24
21
  end
@@ -1,29 +1,18 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
- #
6
3
  # Output/Destination endpoint class
7
- #
8
4
  class Destination
9
5
 
10
6
  include Endpoint
11
7
 
12
8
  attr_reader :entity
13
9
 
14
- # close this output
10
+ # Close this output
15
11
  def close
16
- #error = Map.MIDIClientDispose(@handle)
17
- #raise "MIDIClientDispose returned error code #{error}" unless error.zero?
18
- #error = Map.MIDIPortDispose(@handle)
19
- #raise "MIDIPortDispose returned error code #{error}" unless error.zero?
20
- #error = Map.MIDIEndpointDispose(@resource)
21
- #raise "MIDIEndpointDispose returned error code #{error}" unless error.zero?
22
12
  @enabled = false
23
-
24
13
  end
25
14
 
26
- # sends a MIDI message comprised of a String of hex digits
15
+ # Send a MIDI message comprised of a String of hex digits
27
16
  def puts_s(data)
28
17
  data = data.dup
29
18
  output = []
@@ -35,7 +24,7 @@ module CoreMIDI
35
24
  alias_method :puts_bytestr, :puts_s
36
25
  alias_method :puts_hex, :puts_s
37
26
 
38
- # sends a MIDI messages comprised of Numeric bytes
27
+ # Send a MIDI messages comprised of Numeric bytes
39
28
  def puts_bytes(*data)
40
29
 
41
30
  format = "C" * data.size
@@ -49,7 +38,7 @@ module CoreMIDI
49
38
  end
50
39
  end
51
40
 
52
- # send a MIDI message of an indeterminant type
41
+ # Send a MIDI message of an indeterminant type
53
42
  def puts(*a)
54
43
  case a.first
55
44
  when Array then puts_bytes(*a.first)
@@ -59,7 +48,7 @@ module CoreMIDI
59
48
  end
60
49
  alias_method :write, :puts
61
50
 
62
- # enable this device
51
+ # Enable this device
63
52
  def enable(options = {}, &block)
64
53
  @enabled = true
65
54
  if block_given?
@@ -75,29 +64,28 @@ module CoreMIDI
75
64
  alias_method :open, :enable
76
65
  alias_method :start, :enable
77
66
 
78
- # shortcut to the first output endpoint available
67
+ # Shortcut to the first output endpoint available
79
68
  def self.first
80
69
  Endpoint.first(:destination)
81
70
  end
82
71
 
83
- # shortcut to the last output endpoint available
72
+ # Shortcut to the last output endpoint available
84
73
  def self.last
85
74
  Endpoint.last(:destination)
86
75
  end
87
76
 
88
- # all output endpoints
77
+ # All output endpoints
89
78
  def self.all
90
79
  Endpoint.all_by_type[:destination]
91
80
  end
92
81
 
93
82
  protected
94
83
 
95
- # base initialization for this endpoint -- done whether or not the endpoint is enabled to
84
+ # Base initialization for this endpoint -- done whether or not the endpoint is enabled to
96
85
  # check whether it is truly available for use
97
86
  def connect
98
87
  client_error = enable_client
99
88
  port_error = initialize_port
100
-
101
89
  @resource = Map.MIDIEntityGetDestination( @entity.resource, @resource_id )
102
90
  !@resource.address.zero? && client_error.zero? && port_error.zero?
103
91
  end
@@ -105,24 +93,21 @@ module CoreMIDI
105
93
 
106
94
  private
107
95
 
108
- # output a short MIDI message
96
+ # Output a short MIDI message
109
97
  def puts_small(bytes, size)
110
98
  packet_list = FFI::MemoryPointer.new(256)
111
99
  packet_ptr = Map.MIDIPacketListInit(packet_list)
112
-
113
100
  if Map::SnowLeopard
114
101
  packet_ptr = Map.MIDIPacketListAdd(packet_list, 256, packet_ptr, 0, size, bytes)
115
102
  else
116
103
  # Pass in two 32-bit 0s for the 64 bit time
117
104
  packet_ptr = Map.MIDIPacketListAdd(packet_list, 256, packet_ptr, 0, 0, size, bytes)
118
105
  end
119
-
120
106
  Map.MIDISend( @handle, @resource, packet_list )
121
107
  end
122
108
 
123
- # output a System Exclusive MIDI message
109
+ # Output a System Exclusive MIDI message
124
110
  def puts_sysex(bytes, size)
125
-
126
111
  request = Map::MIDISysexSendRequest.new
127
112
  request[:destination] = @resource
128
113
  request[:data] = bytes
@@ -130,17 +115,15 @@ module CoreMIDI
130
115
  request[:complete] = 0
131
116
  request[:completion_proc] = SysexCompletionCallback
132
117
  request[:completion_ref_con] = request
133
-
134
118
  Map.MIDISendSysex(request)
135
119
  end
136
120
 
137
121
  SysexCompletionCallback =
138
122
  FFI::Function.new(:void, [:pointer]) do |sysex_request_ptr|
139
- # this isn't working for some reason
140
- # as of now, we don't need it though
123
+ # this isn't working for some reason. as of now, it's not needed though
141
124
  end
142
125
 
143
- # initialize a coremidi port for this endpoint
126
+ # Initialize a coremidi port for this endpoint
144
127
  def initialize_port
145
128
  port_name = Map::CF.CFStringCreateWithCString(nil, "Port #{@resource_id}: #{name}", 0)
146
129
  outport_ptr = FFI::MemoryPointer.new(:pointer)
@@ -1,36 +1,44 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
3
  class Device
6
4
 
7
5
  attr_reader :entities,
8
- # unique Numeric id
9
- :id,
10
- # device name from coremidi
11
- :name
6
+ :id, # Unique Numeric id
7
+ :name # Device name from coremidi
12
8
 
13
9
  def initialize(id, device_pointer, options = {})
14
- include_if_offline = options[:include_offline] || false
10
+ include_if_offline = options.fetch(:include_offline, false)
15
11
  @id = id
16
12
  @resource = device_pointer
17
13
  @entities = []
18
-
19
- prop = Map::CF.CFStringCreateWithCString( nil, "name", 0 )
20
- name = Map::CF.CFStringCreateWithCString( nil, id.to_s, 0 )
21
- Map::MIDIObjectGetStringProperty(@resource, prop, name)
22
-
23
- @name = Map::CF.CFStringGetCStringPtr(name.read_pointer, 0).read_string
14
+ populate_name
24
15
  populate_entities(:include_offline => include_if_offline)
25
16
  end
17
+
18
+ # Endpoints for this device
19
+ # @return [Array<Endpoint>]
20
+ def endpoints
21
+ endpoints = { :source => [], :destination => [] }
22
+ endpoints.keys.each do |k|
23
+ endpoints[k] += entities.map { |entity| entity.endpoints[k] }.flatten
24
+ end
25
+ endpoints
26
+ end
26
27
 
27
- # returns all devices which are cached in an instance variable @devices on the Device class
28
- #
29
- # options:
30
- #
31
- # * <b>cache</b>: if false, the device list will never be cached. this would be useful if one needs to alter the device list (e.g. plug in a USB MIDI interface) while their program is running.
32
- # * <b>include_offline</b>: if true, devices marked offline by coremidi will be included in the list
33
- #
28
+ # Assign all of this Device's endpoints an consecutive local id
29
+ # @param [Integer] last_id The highest already used endpoint ID
30
+ # @return [Integer] The highest used endpoint ID after populating this device's endpoints
31
+ def populate_endpoint_ids(last_id)
32
+ i = 0
33
+ entities.each { |entity| i += entity.populate_endpoint_ids(i + last_id) }
34
+ i
35
+ end
36
+
37
+ # All cached devices
38
+ # @param [Hash] options The options to select devices with
39
+ # @option options [Boolean] :cache If false, the device list will never be cached. This would be useful if one needs to alter the device list (e.g. plug in a USB MIDI interface) while their program is running.
40
+ # @option options [Boolean] :include_offline If true, devices marked offline by coremidi will be included in the list
41
+ # @return [Array<Device>] All cached devices
34
42
  def self.all(options = {})
35
43
  use_cache = options[:cache] || true
36
44
  include_offline = options[:include_offline] || false
@@ -46,38 +54,42 @@ module CoreMIDI
46
54
  end
47
55
  @devices
48
56
  end
49
-
50
- # Refresh the Device cash. You'll need to do this if, for instance, you plug in
51
- # a USB MIDI device while the program is running
57
+
58
+ # Refresh the Device cache. This is needed if, for example a USB MIDI device is plugged in while the program is running
59
+ # @return [Array<Device>] The Device cache
52
60
  def self.refresh
53
61
  @devices.clear
54
- end
55
-
56
- # returns all of the Endpoints for this device
57
- def endpoints
58
- endpoints = { :source => [], :destination => [] }
59
- endpoints.keys.each do |k|
60
- endpoints[k] += entities.map { |entity| entity.endpoints[k] }.flatten
61
- end
62
- endpoints
63
- end
64
-
65
- # assign all of this Device's endpoints an consecutive local id
66
- def populate_endpoint_ids(starting_id)
67
- i = 0
68
- entities.each { |entity| i += entity.populate_endpoint_ids(i + starting_id) }
69
- i
62
+ @devices
70
63
  end
71
64
 
72
65
  private
66
+
67
+ # Populate the device name
68
+ def populate_name
69
+ prop = Map::CF.CFStringCreateWithCString( nil, "name", 0 )
70
+
71
+ begin
72
+ name_ptr = FFI::MemoryPointer.new(:pointer)
73
+ Map::MIDIObjectGetStringProperty(@resource, prop, name_ptr)
74
+ name = name_ptr.read_pointer
75
+ len = Map::CF.CFStringGetMaximumSizeForEncoding(Map::CF.CFStringGetLength(name), :kCFStringEncodingUTF8)
76
+ bytes = FFI::MemoryPointer.new(len + 1)
77
+ raise RuntimeError.new("CFStringGetCString") unless Map::CF.CFStringGetCString(name, bytes, len, :kCFStringEncodingUTF8)
78
+ @name = bytes.read_string
79
+ ensure
80
+ Map::CF.CFRelease(name) unless name.nil? || name.null?
81
+ Map::CF.CFRelease(prop) unless prop.null?
82
+ end
83
+ end
73
84
 
74
- # gives all of the endpoints for all devices a consecutive local id
85
+ # All of the endpoints for all devices a consecutive local id
75
86
  def self.populate_endpoint_ids
76
87
  i = 0
77
88
  all.each { |device| i += device.populate_endpoint_ids(i) }
78
89
  end
79
90
 
80
- # populates the entities for this device. these are in turn used to gather the endpoints
91
+ # Populates the entities for this device. These entities are in turn used to gather the endpoints.
92
+ #
81
93
  def populate_entities(options = {})
82
94
  include_if_offline = options[:include_offline] || false
83
95
  i = 0
@@ -1,18 +1,13 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
3
  module Endpoint
6
4
 
7
5
  extend Forwardable
8
6
 
9
- # has the endpoint been initialized?
10
- attr_reader :enabled,
11
- :entity,
12
- # unique local Numeric id of the endpoint
7
+ attr_reader :enabled, # has the endpoint been initialized?
8
+ :entity, # unique local Numeric id of the endpoint
13
9
  :id,
14
- :resource_id,
15
- # :input or :output
10
+ :resource_id, # :input or :output
16
11
  :type
17
12
 
18
13
  def_delegators :entity, :manufacturer, :model, :name
@@ -26,27 +21,27 @@ module CoreMIDI
26
21
  @enabled = false
27
22
  end
28
23
 
29
- # is this endpoint online?
24
+ # Is this endpoint online?
30
25
  def online?
31
26
  @entity.online? && connect?
32
27
  end
33
28
 
34
- # sets the id for this endpoint (the id is immutable once its set)
29
+ # Set the id for this endpoint (the id is immutable once its set)
35
30
  def id=(val)
36
31
  @id ||= val
37
32
  end
38
33
 
39
- # select the first endpoint of type <em>type</em>
34
+ # Select the first endpoint of the specified type
40
35
  def self.first(type)
41
36
  all_by_type[type].first
42
37
  end
43
38
 
44
- # select the last endpoint of type <em>type</em>
39
+ # Select the last endpoint of the specified type
45
40
  def self.last(type)
46
41
  all_by_type[type].last
47
42
  end
48
43
 
49
- # a Hash of :source and :destination endpoints
44
+ # A Hash of :source and :destination endpoints
50
45
  def self.all_by_type
51
46
  {
52
47
  :source => Device.all.map { |d| d.endpoints[:source] }.flatten,
@@ -54,14 +49,14 @@ module CoreMIDI
54
49
  }
55
50
  end
56
51
 
57
- # all endpoints of both types
52
+ # All endpoints of both types
58
53
  def self.all
59
54
  Device.all.map { |d| d.endpoints }.flatten
60
55
  end
61
56
 
62
57
  protected
63
58
 
64
- # enables the coremidi MIDI client that will go with this endpoint
59
+ # Enables the coremidi MIDI client that will go with this endpoint
65
60
  def enable_client
66
61
  client_name = Map::CF.CFStringCreateWithCString( nil, "Client #{@resource_id} #{name}", 0 )
67
62
  client_ptr = FFI::MemoryPointer.new(:pointer)
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
3
  class Entity
@@ -23,7 +21,7 @@ module CoreMIDI
23
21
  @endpoints.keys.each { |type| populate_endpoints(type) }
24
22
  end
25
23
 
26
- # assign all of this Entity's endpoints an consecutive local id
24
+ # Assign all of this Entity's endpoints an consecutive local id
27
25
  def populate_endpoint_ids(starting_id)
28
26
  i = 0
29
27
  @endpoints.values.flatten.each do |e|
@@ -35,7 +33,7 @@ module CoreMIDI
35
33
 
36
34
  private
37
35
 
38
- # populate endpoints of <em>type</em> for this entity
36
+ # Populate endpoints of a specified type for this entity
39
37
  def populate_endpoints(type, options = {})
40
38
  include_if_offline = options[:include_offline] || false
41
39
  endpoint_class = case type
@@ -50,7 +48,7 @@ module CoreMIDI
50
48
  @endpoints[type].size
51
49
  end
52
50
 
53
- # gets the number of endpoints for this entity
51
+ # The number of endpoints for this entity
54
52
  def number_of_endpoints(type)
55
53
  case type
56
54
  when :source then Map.MIDIEntityGetNumberOfSources(@resource)
@@ -58,7 +56,7 @@ module CoreMIDI
58
56
  end
59
57
  end
60
58
 
61
- # gets a CFString property
59
+ # A CFString property
62
60
  def get_string(name, pointer)
63
61
  prop = Map::CF.CFStringCreateWithCString( nil, name.to_s, 0 )
64
62
  val = Map::CF.CFStringCreateWithCString( nil, name.to_s, 0 ) # placeholder
@@ -66,7 +64,7 @@ module CoreMIDI
66
64
  Map::CF.CFStringGetCStringPtr(val.read_pointer, 0).read_string rescue nil
67
65
  end
68
66
 
69
- # gets an Integer property
67
+ # An Integer property
70
68
  def get_int(name, pointer)
71
69
  prop = Map::CF.CFStringCreateWithCString( nil, name.to_s, 0 )
72
70
  val = FFI::MemoryPointer.new(:pointer, 32)
@@ -74,7 +72,7 @@ module CoreMIDI
74
72
  val.read_int
75
73
  end
76
74
 
77
- # gets a CString or Integer property from this Endpoint's entity
75
+ # A CString or Integer property from this Endpoint's entity
78
76
  def get_property(name, options = {})
79
77
  from = options[:from] || @resource
80
78
  type = options[:type] || :string
data/lib/coremidi/map.rb CHANGED
@@ -1,11 +1,6 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
- #
6
- # coremidi binding
7
- #
8
- #
3
+ # Coremidi C binding
9
4
  module Map
10
5
 
11
6
  extend FFI::Library
@@ -122,11 +117,23 @@ module CoreMIDI
122
117
  extend FFI::Library
123
118
  ffi_lib '/System/Library/Frameworks/CoreFoundation.framework/Versions/Current/CoreFoundation'
124
119
 
120
+ typedef :pointer, :CFStringRef
121
+ typedef :long, :CFIndex
122
+ enum :CFStringEncoding, [ :kCFStringEncodingUTF8, 0x08000100 ]
123
+
125
124
  # CFString* CFStringCreateWithCString( ?, CString, encoding)
126
125
  attach_function :CFStringCreateWithCString, [:pointer, :string, :int], :pointer
127
126
  # CString* CFStringGetCStringPtr(CFString*, encoding)
128
127
  attach_function :CFStringGetCStringPtr, [:pointer, :int], :pointer
129
128
 
129
+ attach_function :CFStringGetLength, [ :CFStringRef ], :CFIndex
130
+
131
+ attach_function :CFStringGetMaximumSizeForEncoding, [ :CFIndex, :CFStringEncoding ], :long
132
+
133
+ attach_function :CFStringGetCString, [ :CFStringRef, :pointer, :CFIndex, :CFStringEncoding ], :bool
134
+
135
+ attach_function :CFRelease, [ :pointer ], :void
136
+
130
137
  end
131
138
 
132
139
  module HostTime
@@ -1,10 +1,6 @@
1
- #!/usr/bin/env ruby
2
-
3
1
  module CoreMIDI
4
2
 
5
- #
6
3
  # Input/Source endpoint class
7
- #
8
4
  class Source
9
5
 
10
6
  include Endpoint
@@ -63,7 +59,7 @@ module CoreMIDI
63
59
  alias_method :open, :enable
64
60
  alias_method :start, :enable
65
61
 
66
- # close this input
62
+ # Close this input
67
63
  def close
68
64
  #error = Map.MIDIPortDisconnectSource( @handle, @resource )
69
65
  #raise "MIDIPortDisconnectSource returned error code #{error}" unless error.zero?
@@ -76,25 +72,25 @@ module CoreMIDI
76
72
  @enabled = false
77
73
  end
78
74
 
79
- # shortcut to the first available input endpoint
75
+ # Shortcut to the first available input endpoint
80
76
  def self.first
81
77
  Endpoint.first(:source)
82
78
  end
83
79
 
84
- # shortcut to the last available input endpoint
80
+ # Shortcut to the last available input endpoint
85
81
  def self.last
86
82
  Endpoint.last(:source)
87
83
  end
88
84
 
89
- # all input endpoints
85
+ # All input endpoints
90
86
  def self.all
91
87
  Endpoint.all_by_type[:source]
92
88
  end
93
89
 
94
90
  protected
95
91
 
96
- # base initialization for this endpoint -- done whether or not the endpoint is enabled to
97
- # check whether it is truly available for use
92
+ # Base initialization for this endpoint -- done whether or not the endpoint is enabled to check whether
93
+ # it is truly available for use
98
94
  def connect
99
95
  enable_client
100
96
  initialize_port
@@ -110,17 +106,17 @@ module CoreMIDI
110
106
 
111
107
  private
112
108
 
113
- # returns new MIDI messages from the queue
109
+ # New MIDI messages from the queue
114
110
  def queued_messages
115
111
  @buffer.slice(@pointer, @buffer.length - @pointer)
116
112
  end
117
113
 
118
- # are there new MIDI messages in the queue?
114
+ # Are there new MIDI messages in the queue?
119
115
  def queued_messages?
120
116
  @pointer < @buffer.length
121
117
  end
122
118
 
123
- # the callback which is called by coremidi when new MIDI messages are in the buffer
119
+ # The callback fired by coremidi when new MIDI messages are in the buffer
124
120
  def get_event_callback
125
121
  Proc.new do | new_packets, refCon_ptr, connRefCon_ptr |
126
122
  time = Time.now.to_f
@@ -142,17 +138,17 @@ module CoreMIDI
142
138
  end
143
139
  end
144
140
 
145
- # timestamp
141
+ # Timestamp for a received MIDI message
146
142
  def timestamp(now)
147
143
  ((now - @start_time) * 1000)
148
144
  end
149
145
 
150
- # give a message its timestamp and package it in a Hash
146
+ # Give a message its timestamp and package it in a Hash
151
147
  def get_message_formatted(raw, time)
152
148
  { :data => raw, :timestamp => timestamp(time) }
153
149
  end
154
150
 
155
- # initialize a coremidi port for this endpoint
151
+ # Initialize a coremidi port for this endpoint
156
152
  def initialize_port
157
153
  port_name = Map::CF.CFStringCreateWithCString(nil, "Port #{@resource_id}: #{name}", 0)
158
154
  handle_ptr = FFI::MemoryPointer.new(:pointer)
@@ -162,7 +158,7 @@ module CoreMIDI
162
158
  raise "MIDIInputPortCreate returned error code #{error}" unless error.zero?
163
159
  end
164
160
 
165
- # initialize the MIDI message buffer
161
+ # Initialize the MIDI message buffer
166
162
  def initialize_buffer
167
163
  @pointer = 0
168
164
  @buffer = []
@@ -172,9 +168,7 @@ module CoreMIDI
172
168
  end
173
169
  end
174
170
 
175
- # convert an array of numeric byes to a hex string
176
- # e.g.
177
- # [0x90, 0x40, 0x40] -> "904040"
171
+ # Convert an array of numeric byes to a hex string (e.g. [0x90, 0x40, 0x40] becomes "904040")
178
172
  def numeric_bytes_to_hex_string(bytes)
179
173
  bytes.map { |b| s = b.to_s(16).upcase; b < 16 ? s = "0" + s : s; s }.join
180
174
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-coremidi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-21 00:00:00.000000000 Z
12
+ date: 2013-06-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -45,7 +45,7 @@ files:
45
45
  - test/test_input_buffer.rb
46
46
  - test/test_io.rb
47
47
  - LICENSE
48
- - README.rdoc
48
+ - README.md
49
49
  homepage: http://github.com/arirusso/ffi-coremidi
50
50
  licenses: []
51
51
  post_install_message:
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
66
  version: 1.3.6
67
67
  requirements: []
68
68
  rubyforge_project: ffi-coremidi
69
- rubygems_version: 1.8.23
69
+ rubygems_version: 1.8.25
70
70
  signing_key:
71
71
  specification_version: 3
72
72
  summary: Realtime MIDI IO with Ruby for OSX
data/README.rdoc DELETED
@@ -1,48 +0,0 @@
1
- = ffi-coremidi
2
-
3
- == Summary
4
-
5
- Realtime MIDI IO with Ruby for OSX
6
-
7
- Note that in the interest of allowing people on other platforms to utilize your code, you should consider using {unimidi}[http://github.com/arirusso/unimidi]. Unimidi is a platform independent wrapper that implements this library and has a similar API.
8
-
9
- == Features
10
-
11
- * Simplified API
12
- * Input and output on multiple devices concurrently
13
- * Agnostically handle different MIDI Message types (including SysEx)
14
- * Timestamped input events
15
- * Internally patch MIDI to other programs using IAC (and {MIDI Patch Bay}[http://notahat.com/midi_patchbay] if you're using OSX Snow Leopard or earlier)
16
- == Requirements
17
-
18
- * {ffi}[http://github.com/ffi/ffi] (gem install ffi)
19
-
20
- == Install
21
-
22
- gem install ffi-coremidi
23
-
24
- == Documentation
25
-
26
- * {rdoc}[http://rubydoc.info/github/arirusso/ffi-coremidi]
27
-
28
- == Author
29
-
30
- * {Ari Russo}[http://github.com/arirusso] <ari.russo at gmail.com>
31
-
32
- == Credits
33
-
34
- This library began with some coremidi/ffi binding code for MIDI output by
35
-
36
- * Colin Harris -- http://github.com/aberant
37
-
38
- contained in {his fork of MIDIator}[http://github.com/aberant/midiator] and a {blog post}[http://aberant.tumblr.com/post/694878119/sending-midi-sysex-with-core-midi-and-ruby-ffi]
39
-
40
- {MIDIator}[http://github.com/bleything/midiator] is (c)2008 by Ben Bleything and Topher Cyll and released under the MIT license (see LICENSE.midiator and LICENSE.prp)
41
-
42
- Also thank you to {Jeremy Voorhis}[http://github.com/jvoorhis] for some useful debugging
43
-
44
- == License
45
-
46
- Apache 2.0, See the file LICENSE
47
-
48
- Copyright (c) 2011 Ari Russo