ffi-coremidi 0.3.9 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 548ce7a99e6cb8697066d0d52ce5884efd8437dd
4
- data.tar.gz: 033b84506aafc25fbd008bda1e808ce22aea5a78
2
+ SHA256:
3
+ metadata.gz: dab097a8dd88318d79ef220b1a22a244892a7a410663dab5e7fb98b622621b0a
4
+ data.tar.gz: cbe5cbe19b52e5f728f55342ca1eddaa821c5c1cd2632fa7452c4782a6770950
5
5
  SHA512:
6
- metadata.gz: '09b13413a37eecc61cfeb931780fe721410a37a9e523afda53550e98e38e73435849ade03965b8acebd46155d6ee98e689f3d860ecb1d0b337b5f54d146114f7'
7
- data.tar.gz: 90ec924b77f5fb32ef936712292578f49b6e70d9c7ef28fcc93428333fea229ba88991e976a2c9c59c6e42450755911a458363b377974d7ff7b53349d0f84008
6
+ metadata.gz: 0a2883b3a33e0f67dda8baa3da2458a8bb1c1b027909e1f70a8cd17a28b798c951b57b205c5c81a6a721d13e6477e72b2e5a3150150f4eab436ac1b84bc2a796
7
+ data.tar.gz: 1539a681f754432531c2ec5c806214cef21e4ef688b6ea60d809631d90c36e10a8f7945ecd8fe2dfdb6a8948ec6ea2ef721cc07873a1de83c1352688cd89661d
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2011-2017 Ari Russo
1
+ Copyright 2011-2022 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.
data/README.md CHANGED
@@ -48,4 +48,4 @@ Also thank you to [Jeremy Voorhis](http://github.com/jvoorhis) for some useful d
48
48
 
49
49
  Apache 2.0, See the file LICENSE
50
50
 
51
- Copyright (c) 2011-2017 [Ari Russo](http://github.com/arirusso)
51
+ Copyright (c) 2011-2022 [Ari Russo](http://github.com/arirusso)
data/lib/coremidi/api.rb CHANGED
@@ -1,8 +1,8 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # Coremidi C binding
4
5
  module API
5
-
6
6
  extend FFI::Library
7
7
  ffi_lib '/System/Library/Frameworks/CoreMIDI.framework/Versions/Current/CoreMIDI'
8
8
 
@@ -17,12 +17,11 @@ module CoreMIDI
17
17
  typedef :pointer, :MIDIEntityRef
18
18
  typedef :pointer, :MIDIObjectRef
19
19
  typedef :pointer, :MIDIPortRef
20
- #typedef :pointer, :MIDIReadProc
20
+ # typedef :pointer, :MIDIReadProc
21
21
  typedef :uint32, :MIDITimeStamp
22
22
  typedef :int32, :OSStatus
23
23
 
24
24
  class MIDISysexSendRequest < FFI::Struct
25
-
26
25
  layout :destination, :MIDIEndpointRef,
27
26
  :data, :pointer,
28
27
  :bytes_to_send, :uint32,
@@ -33,18 +32,15 @@ module CoreMIDI
33
32
  end
34
33
 
35
34
  class MIDIPacket < FFI::Struct
36
-
37
35
  layout :timestamp, :MIDITimeStamp,
38
36
  :nothing, :uint32, # no idea...
39
37
  :length, :uint16,
40
38
  :data, [:uint8, 256]
41
-
42
39
  end
43
40
 
44
41
  class MIDIPacketList < FFI::Struct
45
42
  layout :numPackets, :uint32,
46
43
  :packet, [MIDIPacket.by_value, 1]
47
-
48
44
  end
49
45
 
50
46
  def self.get_callback(*args, &block)
@@ -53,7 +49,7 @@ module CoreMIDI
53
49
 
54
50
  # Pack the given data into a coremidi MIDI packet (used by Destination)
55
51
  def self.get_midi_packet(data)
56
- format = "C" * data.size
52
+ format = 'C' * data.size
57
53
  packed_data = data.pack(format)
58
54
  char_size = FFI.type_size(:char) * data.size
59
55
  bytes = FFI::MemoryPointer.new(char_size)
@@ -67,8 +63,8 @@ module CoreMIDI
67
63
  error = API.MIDIClientCreate(client_name, nil, nil, client_pointer)
68
64
  client = client_pointer.read_pointer
69
65
  {
70
- :error => error,
71
- :resource => client
66
+ error: error,
67
+ resource: client
72
68
  }
73
69
  end
74
70
 
@@ -78,8 +74,8 @@ module CoreMIDI
78
74
  error = API.MIDIInputPortCreate(client, port_name, callback, nil, handle_ptr)
79
75
  handle = handle_ptr.read_pointer
80
76
  {
81
- :error => error,
82
- :handle => handle
77
+ error: error,
78
+ handle: handle
83
79
  }
84
80
  end
85
81
 
@@ -89,8 +85,8 @@ module CoreMIDI
89
85
  error = API.MIDIOutputPortCreate(client, port_name, port_pointer)
90
86
  handle = port_pointer.read_pointer
91
87
  {
92
- :error => error,
93
- :handle => handle
88
+ error: error,
89
+ handle: handle
94
90
  }
95
91
  end
96
92
 
@@ -100,11 +96,12 @@ module CoreMIDI
100
96
  packet_ptr = API.MIDIPacketListInit(packet_list)
101
97
  time = HostTime.AudioGetCurrentHostTime
102
98
  packet_ptr = if X86_64
103
- API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time, size, bytes)
104
- else
105
- # Pass in two 32-bit 0s for the 64 bit time
106
- time1 = API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time >> 32, time & 0xFFFFFFFF, size, bytes)
107
- end
99
+ API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time, size, bytes)
100
+ else
101
+ # Pass in two 32-bit 0s for the 64 bit time
102
+ time1 = API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time >> 32, time & 0xFFFFFFFF, size,
103
+ bytes)
104
+ end
108
105
  packet_list
109
106
  end
110
107
 
@@ -132,7 +129,7 @@ module CoreMIDI
132
129
  bytes = FFI::MemoryPointer.new(length + 1)
133
130
 
134
131
  if CF.CFStringGetCString(string, bytes, length + 1, :kCFStringEncodingUTF8)
135
- bytes.read_string.force_encoding("utf-8")
132
+ bytes.read_string.force_encoding('utf-8')
136
133
  end
137
134
  ensure
138
135
  CF.CFRelease(string) unless string.nil? || string.null?
@@ -145,13 +142,13 @@ module CoreMIDI
145
142
  callback :MIDIReadProc, [MIDIPacketList.by_ref, :pointer, :pointer], :pointer
146
143
 
147
144
  # OSStatus MIDIClientCreate(CFStringRef name, MIDINotifyProc notifyProc, void *notifyRefCon, MIDIClientRef *outClient);
148
- attach_function :MIDIClientCreate, [:pointer, :pointer, :pointer, :pointer], :int
145
+ attach_function :MIDIClientCreate, %i[pointer pointer pointer pointer], :int
149
146
 
150
147
  # OSStatus MIDIClientDispose(MIDIClientRef client);
151
148
  attach_function :MIDIClientDispose, [:pointer], :int
152
149
 
153
150
  # MIDIEntityRef MIDIDeviceGetEntity(MIDIDeviceRef device, ItemCount entityIndex0);
154
- attach_function :MIDIDeviceGetEntity, [:MIDIDeviceRef, :ItemCount], :MIDIEntityRef
151
+ attach_function :MIDIDeviceGetEntity, %i[MIDIDeviceRef ItemCount], :MIDIEntityRef
155
152
 
156
153
  # MIDIEndpointRef MIDIGetDestination(ItemCount destIndex0);
157
154
  attach_function :MIDIGetNumberOfDestinations, [], :ItemCount
@@ -162,11 +159,11 @@ module CoreMIDI
162
159
  # MIDIEndpointRef MIDIEntityGetDestination(MIDIEntityRef entity, ItemCount destIndex0);
163
160
  attach_function :MIDIGetDestination, [:int], :pointer
164
161
 
165
- #extern OSStatus MIDIEndpointDispose( MIDIEndpointRef endpt );
162
+ # extern OSStatus MIDIEndpointDispose( MIDIEndpointRef endpt );
166
163
  attach_function :MIDIEndpointDispose, [:MIDIEndpointRef], :OSStatus
167
164
 
168
165
  # MIDIEndpointRef MIDIEntityGetDestination( MIDIEntityRef entity, ItemCount destIndex0 );
169
- attach_function :MIDIEntityGetDestination, [:MIDIEntityRef, :int], :MIDIEndpointRef
166
+ attach_function :MIDIEntityGetDestination, %i[MIDIEntityRef int], :MIDIEndpointRef
170
167
 
171
168
  # ItemCount MIDIEntityGetNumberOfDestinations (MIDIEntityRef entity);
172
169
  attach_function :MIDIEntityGetNumberOfDestinations, [:MIDIEntityRef], :ItemCount
@@ -175,77 +172,76 @@ module CoreMIDI
175
172
  attach_function :MIDIEntityGetNumberOfSources, [:MIDIEntityRef], :ItemCount
176
173
 
177
174
  # MIDIEndpointRef MIDIEntityGetSource (MIDIEntityRef entity, ItemCount sourceIndex0);
178
- attach_function :MIDIEntityGetSource, [:MIDIEntityRef, :ItemCount], :MIDIEndpointRef
175
+ attach_function :MIDIEntityGetSource, %i[MIDIEntityRef ItemCount], :MIDIEndpointRef
179
176
 
180
177
  # MIDIDeviceRef MIDIGetDevice(ItemCount deviceIndex0);
181
178
  attach_function :MIDIGetDevice, [:ItemCount], :MIDIDeviceRef
182
179
 
183
180
  # extern OSStatus MIDIInputPortCreate( MIDIClientRef client, CFStringRef portName,
184
181
  # MIDIReadProc readProc, void * refCon, MIDIPortRef * outPort );
185
- attach_function :MIDIInputPortCreate, [:MIDIClientRef, :CFStringRef, :MIDIReadProc, :pointer, :MIDIPortRef], :OSStatus
182
+ attach_function :MIDIInputPortCreate, %i[MIDIClientRef CFStringRef MIDIReadProc pointer MIDIPortRef],
183
+ :OSStatus
186
184
 
187
185
  # extern OSStatus MIDIObjectGetIntegerProperty( MIDIObjectRef obj, CFStringRef propertyID, SInt32 * outValue );
188
- attach_function :MIDIObjectGetIntegerProperty, [:MIDIObjectRef, :CFStringRef, :pointer], :OSStatus
186
+ attach_function :MIDIObjectGetIntegerProperty, %i[MIDIObjectRef CFStringRef pointer], :OSStatus
189
187
 
190
188
  # OSStatus MIDIObjectGetStringProperty (MIDIObjectRef obj, CFStringRef propertyID, CFStringRef *str);
191
- attach_function :MIDIObjectGetStringProperty, [:MIDIObjectRef, :CFStringRef, :pointer], :OSStatus
189
+ attach_function :MIDIObjectGetStringProperty, %i[MIDIObjectRef CFStringRef pointer], :OSStatus
192
190
 
193
191
  # extern OSStatus MIDIOutputPortCreate( MIDIClientRef client, CFStringRef portName, MIDIPortRef * outPort );
194
- attach_function :MIDIOutputPortCreate, [:MIDIClientRef, :CFStringRef, :pointer], :int
192
+ attach_function :MIDIOutputPortCreate, %i[MIDIClientRef CFStringRef pointer], :int
195
193
 
196
194
  # (MIDIPacket*) MIDIPacketListInit(MIDIPacketList *pktlist);
197
195
  attach_function :MIDIPacketListInit, [:pointer], :pointer
198
196
 
199
- #extern OSStatus MIDIPortConnectSource( MIDIPortRef port, MIDIEndpointRef source, void * connRefCon )
200
- attach_function :MIDIPortConnectSource, [:MIDIPortRef, :MIDIEndpointRef, :pointer], :OSStatus
197
+ # extern OSStatus MIDIPortConnectSource( MIDIPortRef port, MIDIEndpointRef source, void * connRefCon )
198
+ attach_function :MIDIPortConnectSource, %i[MIDIPortRef MIDIEndpointRef pointer], :OSStatus
201
199
 
202
- #extern OSStatus MIDIPortDisconnectSource( MIDIPortRef port, MIDIEndpointRef source );
203
- attach_function :MIDIPortDisconnectSource, [:MIDIPortRef, :MIDIEndpointRef], :OSStatus
200
+ # extern OSStatus MIDIPortDisconnectSource( MIDIPortRef port, MIDIEndpointRef source );
201
+ attach_function :MIDIPortDisconnectSource, %i[MIDIPortRef MIDIEndpointRef], :OSStatus
204
202
 
205
- #extern OSStatus MIDIPortDispose(MIDIPortRef port );
203
+ # extern OSStatus MIDIPortDispose(MIDIPortRef port );
206
204
  attach_function :MIDIPortDispose, [:MIDIPortRef], :OSStatus
207
205
 
208
- #extern OSStatus MIDISend(MIDIPortRef port,MIDIEndpointRef dest,const MIDIPacketList *pktlist);
209
- attach_function :MIDISend, [:MIDIPortRef, :MIDIEndpointRef, :pointer], :int
206
+ # extern OSStatus MIDISend(MIDIPortRef port,MIDIEndpointRef dest,const MIDIPacketList *pktlist);
207
+ attach_function :MIDISend, %i[MIDIPortRef MIDIEndpointRef pointer], :int
210
208
 
211
- #OSStatus MIDISendSysex(MIDISysexSendRequest *request);
209
+ # OSStatus MIDISendSysex(MIDISysexSendRequest *request);
212
210
  attach_function :MIDISendSysex, [:pointer], :int
213
211
 
214
212
  # extern MIDIPacket * MIDIPacketListAdd( MIDIPacketList * pktlist, ByteCount listSize,
215
213
  # MIDIPacket * curPacket, MIDITimeStamp time,
216
214
  # ByteCount nData, const Byte * data)
217
215
  if X86_64
218
- attach_function :MIDIPacketListAdd, [:pointer, :int, :pointer, :uint64, :int, :pointer], :pointer
216
+ attach_function :MIDIPacketListAdd, %i[pointer int pointer uint64 int pointer], :pointer
219
217
  else
220
- attach_function :MIDIPacketListAdd, [:pointer, :int, :pointer, :int, :int, :int, :pointer], :pointer
218
+ attach_function :MIDIPacketListAdd, %i[pointer int pointer int int int pointer], :pointer
221
219
  end
222
220
 
223
221
  module CF
224
-
225
222
  extend FFI::Library
226
223
  ffi_lib '/System/Library/Frameworks/CoreFoundation.framework/Versions/Current/CoreFoundation'
227
224
 
228
225
  typedef :pointer, :CFStringRef
229
226
  typedef :long, :CFIndex
230
- enum :CFStringEncoding, [ :kCFStringEncodingUTF8, 0x08000100 ]
227
+ enum :CFStringEncoding, [:kCFStringEncodingUTF8, 0x08000100]
231
228
 
232
229
  # CFString* CFStringCreateWithCString( ?, CString, encoding)
233
- attach_function :CFStringCreateWithCString, [:pointer, :string, :int], :pointer
230
+ attach_function :CFStringCreateWithCString, %i[pointer string int], :pointer
234
231
  # CString* CFStringGetCStringPtr(CFString*, encoding)
235
- attach_function :CFStringGetCStringPtr, [:pointer, :int], :pointer
232
+ attach_function :CFStringGetCStringPtr, %i[pointer int], :pointer
236
233
 
237
234
  # CFIndex CFStringGetLength(CFStringRef theString);
238
- attach_function :CFStringGetLength, [ :CFStringRef ], :CFIndex
235
+ attach_function :CFStringGetLength, [:CFStringRef], :CFIndex
239
236
 
240
237
  # CFIndex CFStringGetMaximumSizeForEncoding(CFIndex length, CFStringEncoding encoding);
241
- attach_function :CFStringGetMaximumSizeForEncoding, [ :CFIndex, :CFStringEncoding ], :long
238
+ attach_function :CFStringGetMaximumSizeForEncoding, %i[CFIndex CFStringEncoding], :long
242
239
 
243
240
  # Boolean CFStringGetCString(CFStringRef theString, char *buffer, CFIndex bufferSize, CFStringEncoding encoding);
244
- attach_function :CFStringGetCString, [ :CFStringRef, :pointer, :CFIndex, :CFStringEncoding ], :bool
241
+ attach_function :CFStringGetCString, %i[CFStringRef pointer CFIndex CFStringEncoding], :bool
245
242
 
246
243
  # void CFRelease (CFTypeRef cf);
247
- attach_function :CFRelease, [ :pointer ], :void
248
-
244
+ attach_function :CFRelease, [:pointer], :void
249
245
  end
250
246
 
251
247
  module HostTime
@@ -257,7 +253,5 @@ module CoreMIDI
257
253
  # UInt64 AudioGetCurrentHostTime()
258
254
  attach_function :AudioGetCurrentHostTime, [], :uint64
259
255
  end
260
-
261
256
  end
262
-
263
257
  end
@@ -1,8 +1,8 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # Type of endpoint used for output
4
5
  class Destination
5
-
6
6
  include Endpoint
7
7
 
8
8
  attr_reader :entity
@@ -24,14 +24,14 @@ module CoreMIDI
24
24
  def puts_s(data)
25
25
  data = data.dup
26
26
  bytes = []
27
- until (str = data.slice!(0,2)).eql?("")
27
+ until (str = data.slice!(0, 2)).eql?('')
28
28
  bytes << str.hex
29
29
  end
30
30
  puts_bytes(*bytes)
31
31
  true
32
32
  end
33
- alias_method :puts_bytestr, :puts_s
34
- alias_method :puts_hex, :puts_s
33
+ alias puts_bytestr puts_s
34
+ alias puts_hex puts_s
35
35
 
36
36
  # Send a MIDI message comprised of numeric bytes
37
37
  # @param [*Integer] data Numeric bytes eg 0x90, 0x40, 0x40
@@ -39,7 +39,7 @@ module CoreMIDI
39
39
  def puts_bytes(*data)
40
40
  type = sysex?(data) ? :sysex : :small
41
41
  bytes = API.get_midi_packet(data)
42
- send("puts_#{type.to_s}", bytes, data.size)
42
+ send("puts_#{type}", bytes, data.size)
43
43
  true
44
44
  end
45
45
 
@@ -53,12 +53,12 @@ module CoreMIDI
53
53
  when String then puts_bytestr(*args)
54
54
  end
55
55
  end
56
- alias_method :write, :puts
56
+ alias write puts
57
57
 
58
58
  # Enable this device
59
59
  # @return [Destination]
60
- def enable(options = {}, &block)
61
- @enabled = true unless @enabled
60
+ def enable(_options = {})
61
+ @enabled ||= true
62
62
  if block_given?
63
63
  begin
64
64
  yield(self)
@@ -68,8 +68,8 @@ module CoreMIDI
68
68
  end
69
69
  self
70
70
  end
71
- alias_method :open, :enable
72
- alias_method :start, :enable
71
+ alias open enable
72
+ alias start enable
73
73
 
74
74
  # Shortcut to the first output endpoint available
75
75
  # @return [Destination]
@@ -97,10 +97,10 @@ module CoreMIDI
97
97
  def connect
98
98
  client_error = enable_client
99
99
  port_error = initialize_port
100
- @resource = API.MIDIEntityGetDestination( @entity.resource, @resource_id )
100
+ @resource = API.MIDIEntityGetDestination(@entity.resource, @resource_id)
101
101
  !@resource.address.zero? && client_error.zero? && port_error.zero?
102
102
  end
103
- alias_method :connect?, :connect
103
+ alias connect? connect
104
104
 
105
105
  private
106
106
 
@@ -126,7 +126,7 @@ module CoreMIDI
126
126
 
127
127
  SysexCompletionCallback =
128
128
  API.get_callback([:pointer]) do |sysex_request_ptr|
129
- # this isn't working for some reason. as of now, it's not needed though
129
+ # this isn't working for some reason. as of now, it's not needed though
130
130
  end
131
131
 
132
132
  # Initialize a coremidi port for this endpoint
@@ -140,7 +140,5 @@ module CoreMIDI
140
140
  def sysex?(data)
141
141
  data.first.eql?(0xF0) && data.last.eql?(0xF7)
142
142
  end
143
-
144
143
  end
145
-
146
144
  end
@@ -1,12 +1,12 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # A MIDI device may have multiple logically distinct sub-components. For example, one device may
4
5
  # encompass a MIDI synthesizer and a pair of MIDI ports, both addressable via a USB port. Each
5
6
  # such element of a device is called a MIDI entity.
6
7
  #
7
8
  # https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/Reference/reference.html
8
9
  class Device
9
-
10
10
  attr_reader :entities,
11
11
  :id, # Unique Numeric id
12
12
  :name # Device name from coremidi
@@ -25,8 +25,8 @@ module CoreMIDI
25
25
  # Endpoints for this device
26
26
  # @return [Array<Endpoint>]
27
27
  def endpoints
28
- endpoints = { :source => [], :destination => [] }
29
- endpoints.keys.each do |key|
28
+ endpoints = { source: [], destination: [] }
29
+ endpoints.each_key do |key|
30
30
  endpoint_group = entities.map { |entity| entity.endpoints[key] }.flatten
31
31
  endpoints[key] += endpoint_group
32
32
  end
@@ -53,8 +53,8 @@ module CoreMIDI
53
53
  if !populated? || !use_cache
54
54
  @devices = []
55
55
  counter = 0
56
- while !(device_pointer = API.MIDIGetDevice(counter)).null?
57
- device = new(counter, device_pointer, :include_offline => include_offline)
56
+ until (device_pointer = API.MIDIGetDevice(counter)).null?
57
+ device = new(counter, device_pointer, include_offline: include_offline)
58
58
  @devices << device
59
59
  counter += 1
60
60
  end
@@ -79,8 +79,8 @@ module CoreMIDI
79
79
 
80
80
  # Populate the device name
81
81
  def populate_name
82
- @name = API.get_string(@resource, "name")
83
- raise RuntimeError.new("Can't get device name") unless @name
82
+ @name = API.get_string(@resource, 'name')
83
+ raise "Can't get device name" unless @name
84
84
  end
85
85
 
86
86
  # All of the endpoints for all devices a consecutive local id
@@ -97,8 +97,8 @@ module CoreMIDI
97
97
  def populate_entities(options = {})
98
98
  include_if_offline = options[:include_offline] || false
99
99
  i = 0
100
- while !(entity_pointer = API.MIDIDeviceGetEntity(@resource, i)).null?
101
- @entities << Entity.new(entity_pointer, :include_offline => include_if_offline)
100
+ until (entity_pointer = API.MIDIDeviceGetEntity(@resource, i)).null?
101
+ @entities << Entity.new(entity_pointer, include_offline: include_if_offline)
102
102
  i += 1
103
103
  end
104
104
  i
@@ -107,9 +107,7 @@ module CoreMIDI
107
107
  # Populate the instance
108
108
  def populate(options = {})
109
109
  populate_name
110
- populate_entities(:include_offline => options[:include_offline])
110
+ populate_entities(include_offline: options[:include_offline])
111
111
  end
112
-
113
112
  end
114
-
115
113
  end
@@ -1,10 +1,10 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # A source or destination of a 16-channel MIDI stream
4
5
  #
5
6
  # https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/Reference/reference.html
6
7
  module Endpoint
7
-
8
8
  extend Forwardable
9
9
 
10
10
  attr_reader :enabled, # has the endpoint been initialized?
@@ -15,7 +15,7 @@ module CoreMIDI
15
15
 
16
16
  def_delegators :entity, :manufacturer, :model, :name
17
17
 
18
- alias_method :enabled?, :enabled
18
+ alias enabled? enabled
19
19
 
20
20
  # @param [Integer] resource_id
21
21
  # @param [Entity] entity
@@ -24,6 +24,9 @@ module CoreMIDI
24
24
  @resource_id = resource_id
25
25
  @type = get_type
26
26
  @enabled = false
27
+
28
+ @threads_sync_semaphore = Mutex.new
29
+ @threads_waiting = []
27
30
  end
28
31
 
29
32
  # Is this endpoint online?
@@ -67,8 +70,8 @@ module CoreMIDI
67
70
  # @return [Hash]
68
71
  def self.all_by_type
69
72
  {
70
- :source => sources,
71
- :destination => destinations
73
+ source: sources,
74
+ destination: destinations
72
75
  }
73
76
  end
74
77
 
@@ -102,7 +105,5 @@ module CoreMIDI
102
105
  @client = client[:resource]
103
106
  client[:error]
104
107
  end
105
-
106
108
  end
107
-
108
109
  end
@@ -1,5 +1,6 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # A MIDI entity can have any number of MIDI endpoints, each of which is a source or destination
4
5
  # of a 16-channel MIDI stream. By grouping a device's endpoints into entities, the system has
5
6
  # enough information for an application to make reasonable default assumptions about how to
@@ -8,7 +9,6 @@ module CoreMIDI
8
9
  #
9
10
  # https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/Reference/reference.html
10
11
  class Entity
11
-
12
12
  attr_reader :endpoints,
13
13
  :manufacturer,
14
14
  :model,
@@ -20,8 +20,8 @@ module CoreMIDI
20
20
  # @option options [Boolean] :include_offline Include offline endpoints in the list
21
21
  def initialize(resource, options = {})
22
22
  @endpoints = {
23
- :source => [],
24
- :destination => []
23
+ source: [],
24
+ destination: []
25
25
  }
26
26
  @resource = resource
27
27
  populate(options)
@@ -31,18 +31,13 @@ module CoreMIDI
31
31
  # @param [Integer] starting_id
32
32
  # @return [Integer]
33
33
  def populate_endpoint_ids(starting_id)
34
- counter = 0
35
- @endpoints.values.flatten.each do |endpoint|
36
- endpoint.id = counter + starting_id
37
- counter += 1
38
- end
39
- counter
34
+ @endpoints.values.flatten.map.with_index { |endpoint, index| endpoint.id = index + starting_id }.length
40
35
  end
41
36
 
42
37
  # Is the entity online?
43
38
  # @return [Boolean]
44
39
  def online?
45
- get_int(:offline) == 0
40
+ get_int(:offline).zero?
46
41
  end
47
42
 
48
43
  private
@@ -63,9 +58,8 @@ module CoreMIDI
63
58
  num_endpoints = number_of_endpoints(type)
64
59
  (0..num_endpoints).each do |i|
65
60
  endpoint = endpoint_class.new(i, self)
66
- if endpoint.online? || options[:include_offline]
67
- @endpoints[type] << endpoint
68
- end
61
+ should_include_message = endpoint.online? || options[:include_offline]
62
+ @endpoints[type] << endpoint if should_include_message
69
63
  end
70
64
  @endpoints[type].size
71
65
  end
@@ -82,8 +76,8 @@ module CoreMIDI
82
76
  # @param [Symbol] type The endpoint type eg :source, :destination
83
77
  def number_of_endpoints(type)
84
78
  case type
85
- when :source then API.MIDIEntityGetNumberOfSources(@resource)
86
- when :destination then API.MIDIEntityGetNumberOfDestinations(@resource)
79
+ when :source then API.MIDIEntityGetNumberOfSources(@resource)
80
+ when :destination then API.MIDIEntityGetNumberOfDestinations(@resource)
87
81
  end
88
82
  end
89
83
 
@@ -110,7 +104,5 @@ module CoreMIDI
110
104
  @name = get_name
111
105
  populate_endpoints(options)
112
106
  end
113
-
114
107
  end
115
-
116
108
  end
@@ -1,11 +1,16 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
+ module CoreMIDI
3
4
  # Type of endpoint used for input
4
5
  class Source
5
-
6
6
  include Endpoint
7
7
 
8
- attr_reader :buffer
8
+ # The buffer of received messages since instantiation
9
+ # @return [Array<Hash>]
10
+ def buffer
11
+ fill_buffer
12
+ @buffer
13
+ end
9
14
 
10
15
  #
11
16
  # An array of MIDI event hashes as such:
@@ -20,15 +25,9 @@ module CoreMIDI
20
25
  #
21
26
  # @return [Array<Hash>]
22
27
  def gets
23
- until queued_messages?
24
- # per https://github.com/arirusso/unimidi/issues/20#issuecomment-44761318
25
- sleep(0.0001) # patch to prevent 100% CPU issue with some midi controllers
26
- end
27
- messages = queued_messages
28
- @pointer = @buffer.length
29
- messages
28
+ fill_buffer(locking: true)
30
29
  end
31
- alias_method :read, :gets
30
+ alias read gets
32
31
 
33
32
  # Same as Source#gets except that it returns message data as string of hex
34
33
  # digits as such:
@@ -46,12 +45,12 @@ module CoreMIDI
46
45
  end
47
46
  messages
48
47
  end
49
- alias_method :gets_bytestr, :gets_s
48
+ alias gets_bytestr gets_s
50
49
 
51
50
  # Enable this the input for use; can be passed a block
52
51
  # @return [Source]
53
- def enable(options = {}, &block)
54
- @enabled = true unless @enabled
52
+ def enable(_options = {})
53
+ @enabled ||= true
55
54
  if block_given?
56
55
  begin
57
56
  yield(self)
@@ -61,20 +60,20 @@ module CoreMIDI
61
60
  end
62
61
  self
63
62
  end
64
- alias_method :open, :enable
65
- alias_method :start, :enable
63
+ alias open enable
64
+ alias start enable
66
65
 
67
66
  # Close this input
68
67
  # @return [Boolean]
69
68
  def close
70
- #error = API.MIDIPortDisconnectSource( @handle, @resource )
71
- #raise "MIDIPortDisconnectSource returned error code #{error}" unless error.zero?
72
- #error = API.MIDIClientDispose(@handle)
73
- #raise "MIDIClientDispose returned error code #{error}" unless error.zero?
74
- #error = API.MIDIPortDispose(@handle)
75
- #raise "MIDIPortDispose returned error code #{error}" unless error.zero?
76
- #error = API.MIDIEndpointDispose(@resource)
77
- #raise "MIDIEndpointDispose returned error code #{error}" unless error.zero?
69
+ # error = API.MIDIPortDisconnectSource( @handle, @resource )
70
+ # raise "MIDIPortDisconnectSource returned error code #{error}" unless error.zero?
71
+ # error = API.MIDIClientDispose(@handle)
72
+ # raise "MIDIClientDispose returned error code #{error}" unless error.zero?
73
+ # error = API.MIDIPortDispose(@handle)
74
+ # raise "MIDIPortDispose returned error code #{error}" unless error.zero?
75
+ # error = API.MIDIEndpointDispose(@resource)
76
+ # raise "MIDIEndpointDispose returned error code #{error}" unless error.zero?
78
77
  if @enabled
79
78
  @enabled = false
80
79
  true
@@ -103,25 +102,50 @@ module CoreMIDI
103
102
 
104
103
  protected
105
104
 
105
+ def truncate_buffer
106
+ @buffer.slice!(-1024, 1024)
107
+ end
108
+
109
+ # Migrate new received messages from the callback queue to
110
+ # the buffer
111
+ def fill_buffer(locking: nil)
112
+ locking ||= false
113
+
114
+ messages = []
115
+
116
+ if locking && @queue.empty?
117
+ @threads_sync_semaphore.synchronize do
118
+ @threads_waiting << Thread.current
119
+ end
120
+ sleep
121
+ end
122
+
123
+ messages << @queue.pop until @queue.empty?
124
+ @buffer += messages
125
+ truncate_buffer
126
+ @pointer = @buffer.length
127
+ messages
128
+ end
129
+
106
130
  # Base initialization for this endpoint -- done whether or not the endpoint is enabled to check whether
107
131
  # it is truly available for use
108
132
  def connect
109
133
  enable_client
110
134
  initialize_port
111
135
  @resource = API.MIDIEntityGetSource(@entity.resource, @resource_id)
112
- error = API.MIDIPortConnectSource(@handle, @resource, nil )
136
+ error = API.MIDIPortConnectSource(@handle, @resource, nil)
113
137
  initialize_buffer
138
+ @queue = Queue.new
114
139
  @sysex_buffer = []
115
- @start_time = Time.now.to_f
116
140
 
117
141
  error.zero?
118
142
  end
119
- alias_method :connect?, :connect
143
+ alias connect? connect
120
144
 
121
145
  private
122
146
 
123
- # Add a single message to the buffer
124
- # @param [Array<Integer>] bytes Message data
147
+ # Add a single message to the callback queue
148
+ # @param [Array<Fixnum>] bytes Message data
125
149
  # @param [Float] timestamp The system float timestamp
126
150
  # @return [Array<Hash>] The resulting buffer
127
151
  def enqueue_message(bytes, timestamp)
@@ -132,62 +156,61 @@ module CoreMIDI
132
156
  @sysex_buffer.clear
133
157
  end
134
158
  end
135
- @buffer << get_message_formatted(bytes, timestamp) if @sysex_buffer.empty?
136
- @buffer
137
- end
159
+ message = get_message_formatted(bytes, timestamp)
160
+ @queue << message
138
161
 
139
- # New MIDI messages from the queue
140
- def queued_messages
141
- @buffer.slice(@pointer, @buffer.length - @pointer)
142
- end
162
+ @threads_sync_semaphore.synchronize do
163
+ @threads_waiting.each(&:run)
164
+ @threads_waiting.clear
165
+ end
143
166
 
144
- # Are there new MIDI messages in the queue?
145
- def queued_messages?
146
- @pointer < @buffer.length
167
+ message
147
168
  end
148
169
 
149
- # The callback fired by coremidi when new MIDI messages are in the buffer
170
+ # The callback fired by coremidi when new MIDI messages are received
150
171
  def get_event_callback
151
- Proc.new do |new_packets, refCon_ptr, connRefCon_ptr|
172
+ Thread.abort_on_exception = true
173
+ proc do |new_packets, _refCon_ptr, _connRefCon_ptr|
152
174
  begin
153
- # p "packets received: #{new_packets[:numPackets]}"
154
175
  timestamp = Time.now.to_f
155
176
  messages = get_messages(new_packets)
156
- messages.each { |message| enqueue_message(message, timestamp) }
157
- rescue Exception => exception
158
- Thread.main.raise(exception)
177
+ messages.each do |message|
178
+ enqueue_message(message, timestamp)
179
+ end
180
+ rescue Exception => e
181
+ Thread.main.raise(e)
159
182
  end
160
183
  end
161
184
  end
162
185
 
163
186
  # Get MIDI messages from the given CoreMIDI packet list
164
187
  # @param [API::MIDIPacketList] new_packets The packet list
165
- # @return [Array<Array<Integer>>] A collection of MIDI messages
188
+ # @return [Array<Array<Fixnum>>] A collection of MIDI messages
166
189
  def get_messages(packet_list)
167
190
  count = packet_list[:numPackets]
168
191
  first = packet_list[:packet][0]
169
192
  data = first[:data].to_a
170
193
  messages = []
171
194
  messages << data.slice!(0, first[:length])
172
- (count - 1).times do |i|
195
+ (count - 1).times do |_i|
173
196
  length_index = find_next_length_index(data)
174
197
  message_length = data[length_index]
175
- unless message_length.nil?
176
- packet_start_index = length_index + 2
177
- packet_end_index = packet_start_index + message_length
178
- if data.length >= packet_end_index + 1
179
- packet = data.slice!(0..packet_end_index)
180
- message = packet.slice(packet_start_index, message_length)
181
- messages << message
182
- end
183
- end
198
+ next if message_length.nil?
199
+
200
+ packet_start_index = length_index + 2
201
+ packet_end_index = packet_start_index + message_length
202
+ next unless data.length >= packet_end_index + 1
203
+
204
+ packet = data.slice!(0..packet_end_index)
205
+ message = packet.slice(packet_start_index, message_length)
206
+ messages << message
184
207
  end
185
208
  messages
186
209
  end
187
210
 
188
211
  # Get the next index for "length" from the blob of MIDI data
189
- # @param [Array<Integer>] data
190
- # @return [Integer]
212
+ # @param [Array<Fixnum>] data
213
+ # @return [Fixnum]
191
214
  def find_next_length_index(data)
192
215
  last_is_zero = false
193
216
  data.each_with_index do |num, i|
@@ -203,18 +226,12 @@ module CoreMIDI
203
226
  end
204
227
  end
205
228
 
206
- # Timestamp for a received MIDI message
207
- # @return [Integer]
208
- def timestamp(now)
209
- (now - @start_time) * 1000
210
- end
211
-
212
229
  # Give a message its timestamp and package it in a Hash
213
230
  # @return [Hash]
214
231
  def get_message_formatted(raw, time)
215
232
  {
216
- :data => raw,
217
- :timestamp => timestamp(time)
233
+ data: raw,
234
+ timestamp: time
218
235
  }
219
236
  end
220
237
 
@@ -225,6 +242,7 @@ module CoreMIDI
225
242
  port = API.create_midi_input_port(@client, @resource_id, @name, @callback)
226
243
  @handle = port[:handle]
227
244
  raise "MIDIInputPortCreate returned error code #{port[:error]}" unless port[:error].zero?
245
+
228
246
  true
229
247
  end
230
248
 
@@ -239,7 +257,5 @@ module CoreMIDI
239
257
  end
240
258
  true
241
259
  end
242
-
243
260
  end
244
-
245
261
  end
@@ -1,9 +1,9 @@
1
- module CoreMIDI
1
+ # frozen_string_literal: true
2
2
 
3
- # Helper for convertig MIDI data
3
+ module CoreMIDI
4
+ # Helper for converting MIDI data
4
5
  module TypeConversion
5
-
6
- extend self
6
+ module_function
7
7
 
8
8
  # Convert an array of numeric byes to a hex string (e.g. [0x90, 0x40, 0x40] becomes "904040")
9
9
  # @param [Array<Integer>] bytes
@@ -11,11 +11,10 @@ module CoreMIDI
11
11
  def numeric_bytes_to_hex_string(bytes)
12
12
  string_bytes = bytes.map do |byte|
13
13
  str = byte.to_s(16).upcase
14
- str = "0" + str if byte < 16
14
+ str = "0#{str}" if byte < 16
15
15
  str
16
16
  end
17
17
  string_bytes.join
18
- end
19
-
18
+ end
20
19
  end
21
20
  end
data/lib/coremidi.rb CHANGED
@@ -1,26 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # ffi-coremidi
3
5
  # Realtime MIDI IO with Ruby for OSX
4
6
  #
5
- # (c)2011-2017 Ari Russo
7
+ # (c)2011-2022 Ari Russo
6
8
  # https://github.com/arirusso/ffi-coremidi
7
9
  #
8
10
 
9
11
  # Libs
10
- require "ffi"
11
- require "forwardable"
12
+ require 'ffi'
13
+ require 'forwardable'
12
14
 
13
15
  # Modules
14
- require "coremidi/api"
15
- require "coremidi/endpoint"
16
- require "coremidi/type_conversion"
16
+ require 'coremidi/api'
17
+ require 'coremidi/endpoint'
18
+ require 'coremidi/type_conversion'
17
19
 
18
20
  # Classes
19
- require "coremidi/entity"
20
- require "coremidi/device"
21
- require "coremidi/source"
22
- require "coremidi/destination"
21
+ require 'coremidi/entity'
22
+ require 'coremidi/device'
23
+ require 'coremidi/source'
24
+ require 'coremidi/destination'
23
25
 
24
26
  module CoreMIDI
25
- VERSION = "0.3.9"
27
+ VERSION = '0.5.1'
26
28
  end
metadata CHANGED
@@ -1,115 +1,95 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-coremidi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Russo
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-07 00:00:00.000000000 Z
11
+ date: 2022-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: minitest
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.5'
19
+ version: '13.0'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 5.5.0
22
+ version: 13.0.6
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '5.5'
29
+ version: '13.0'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 5.5.0
32
+ version: 13.0.6
33
33
  - !ruby/object:Gem::Dependency
34
- name: mocha
34
+ name: rspec
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '1.1'
40
37
  - - ">="
41
38
  - !ruby/object:Gem::Version
42
- version: 1.1.0
43
- type: :development
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '1.1'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 1.1.0
53
- - !ruby/object:Gem::Dependency
54
- name: rake
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
39
+ version: 3.11.0
57
40
  - - "~>"
58
41
  - !ruby/object:Gem::Version
59
- version: '10.4'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 10.4.2
42
+ version: '3.11'
63
43
  type: :development
64
44
  prerelease: false
65
45
  version_requirements: !ruby/object:Gem::Requirement
66
46
  requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '10.4'
70
47
  - - ">="
71
48
  - !ruby/object:Gem::Version
72
- version: 10.4.2
49
+ version: 3.11.0
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.11'
73
53
  - !ruby/object:Gem::Dependency
74
- name: shoulda-context
54
+ name: rubocop
75
55
  requirement: !ruby/object:Gem::Requirement
76
56
  requirements:
77
- - - "~>"
78
- - !ruby/object:Gem::Version
79
- version: '1.2'
80
57
  - - ">="
81
58
  - !ruby/object:Gem::Version
82
- version: 1.2.1
59
+ version: 1.10.0
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.10'
83
63
  type: :development
84
64
  prerelease: false
85
65
  version_requirements: !ruby/object:Gem::Requirement
86
66
  requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '1.2'
90
67
  - - ">="
91
68
  - !ruby/object:Gem::Version
92
- version: 1.2.1
69
+ version: 1.10.0
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: '1.10'
93
73
  - !ruby/object:Gem::Dependency
94
74
  name: ffi
95
75
  requirement: !ruby/object:Gem::Requirement
96
76
  requirements:
97
77
  - - "~>"
98
78
  - !ruby/object:Gem::Version
99
- version: '1.9'
79
+ version: '1.15'
100
80
  - - ">="
101
81
  - !ruby/object:Gem::Version
102
- version: 1.9.6
82
+ version: 1.15.5
103
83
  type: :runtime
104
84
  prerelease: false
105
85
  version_requirements: !ruby/object:Gem::Requirement
106
86
  requirements:
107
87
  - - "~>"
108
88
  - !ruby/object:Gem::Version
109
- version: '1.9'
89
+ version: '1.15'
110
90
  - - ">="
111
91
  - !ruby/object:Gem::Version
112
- version: 1.9.6
92
+ version: 1.15.5
113
93
  description: Perform realtime MIDI IO with Ruby for OSX
114
94
  email:
115
95
  - ari.russo@gmail.com
@@ -127,14 +107,11 @@ files:
127
107
  - lib/coremidi/entity.rb
128
108
  - lib/coremidi/source.rb
129
109
  - lib/coremidi/type_conversion.rb
130
- - test/helper.rb
131
- - test/input_buffer_test.rb
132
- - test/io_test.rb
133
110
  homepage: http://github.com/arirusso/ffi-coremidi
134
111
  licenses:
135
112
  - Apache-2.0
136
113
  metadata: {}
137
- post_install_message:
114
+ post_install_message:
138
115
  rdoc_options: []
139
116
  require_paths:
140
117
  - lib
@@ -147,11 +124,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
124
  requirements:
148
125
  - - ">="
149
126
  - !ruby/object:Gem::Version
150
- version: 1.3.6
127
+ version: '0'
151
128
  requirements: []
152
- rubyforge_project: ffi-coremidi
153
- rubygems_version: 2.6.8
154
- signing_key:
129
+ rubygems_version: 3.0.9
130
+ signing_key:
155
131
  specification_version: 4
156
132
  summary: Realtime MIDI IO with Ruby for OSX
157
133
  test_files: []
data/test/helper.rb DELETED
@@ -1,66 +0,0 @@
1
- dir = File.dirname(File.expand_path(__FILE__))
2
- $LOAD_PATH.unshift dir + "/../lib"
3
-
4
- require "minitest/autorun"
5
- require "mocha/test_unit"
6
- require "shoulda-context"
7
-
8
- require "coremidi"
9
-
10
- module TestHelper
11
-
12
- extend self
13
-
14
- def device
15
- @device ||= select_devices
16
- end
17
-
18
- def select_devices
19
- @device ||= {}
20
- { :input => CoreMIDI::Source.all, :output => CoreMIDI::Destination.all }.each do |type, devs|
21
- puts ""
22
- puts "select an #{type.to_s}..."
23
- while @device[type].nil?
24
- devs.each do |device|
25
- puts "#{device.id}: #{device.name}"
26
- end
27
- selection = $stdin.gets.chomp
28
- if selection != ""
29
- selection = selection.to_i
30
- @device[type] = devs.find { |d| d.id == selection }
31
- puts "selected #{selection} for #{type.to_s}" unless @device[type]
32
- end
33
- end
34
- end
35
- @device
36
- end
37
-
38
- def bytestrs_to_ints(arr)
39
- data = arr.map { |m| m[:data] }.join
40
- output = []
41
- until (bytestr = data.slice!(0,2)).eql?("")
42
- output << bytestr.hex
43
- end
44
- output
45
- end
46
-
47
- # some MIDI messages
48
- VariousMIDIMessages = [
49
- [0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7], # SysEx
50
- [0x90, 100, 100], # note on
51
- [0x90, 43, 100], # note on
52
- [0x90, 76, 100], # note on
53
- [0x90, 60, 100], # note on
54
- [0x80, 100, 100] # note off
55
- ]
56
-
57
- # some MIDI messages
58
- VariousMIDIByteStrMessages = [
59
- "F04110421240007F0041F7", # SysEx
60
- "906440", # note on
61
- "804340" # note off
62
- ]
63
-
64
- end
65
-
66
- TestHelper.select_devices
@@ -1,42 +0,0 @@
1
- require "helper"
2
-
3
- class InputBufferTest < Minitest::Test
4
-
5
- context "CoreMIDI" do
6
-
7
- setup do
8
- sleep(1)
9
- end
10
-
11
- context "Source#buffer" do
12
-
13
- setup do
14
- @messages = TestHelper::VariousMIDIMessages
15
- @messages_arr = @messages.inject { |a,b| a+b }.flatten
16
- @received_arr = []
17
- @pointer = 0
18
-
19
- @output = TestHelper.device[:output].open
20
- @input = TestHelper.device[:input].open
21
- @input.buffer.clear
22
- end
23
-
24
- should "have the correct messages in the buffer" do
25
- bytes = []
26
- @messages.each do |message|
27
- puts "sending: #{message.inspect}"
28
- @output.puts(message)
29
- bytes += message
30
-
31
- sleep(0.5)
32
-
33
- buffer = @input.buffer.map { |m| m[:data] }.flatten
34
- puts "received: #{buffer.to_s}"
35
- assert_equal(bytes, buffer)
36
- end
37
- assert_equal(bytes.length, @input.buffer.map { |m| m[:data] }.flatten.length)
38
- end
39
- end
40
-
41
- end
42
- end
data/test/io_test.rb DELETED
@@ -1,90 +0,0 @@
1
- require "helper"
2
-
3
- class CoreMIDI::IOTest < Minitest::Test
4
-
5
- # ** these tests assume that TestOutput is connected to TestInput
6
- context "CoreMIDI" do
7
-
8
- setup do
9
- sleep(1)
10
- end
11
-
12
- context "full IO" do
13
-
14
- context "using Arrays" do
15
-
16
- setup do
17
- @messages = TestHelper::VariousMIDIMessages
18
- @messages_arr = @messages.inject { |a,b| a+b }.flatten
19
- @received_arr = []
20
- @pointer = 0
21
- end
22
-
23
- should "do IO" do
24
- TestHelper.device[:output].open do |output|
25
- TestHelper.device[:input].open do |input|
26
-
27
- input.buffer.clear
28
-
29
- @messages.each do |msg|
30
-
31
- $>.puts "sending: " + msg.inspect
32
-
33
- output.puts(msg)
34
- sleep(1)
35
- received = input.gets.map { |m| m[:data] }.flatten
36
-
37
- $>.puts "received: " + received.inspect
38
-
39
- assert_equal(@messages_arr.slice(@pointer, received.length), received)
40
- @pointer += received.length
41
- @received_arr += received
42
- end
43
- assert_equal(@messages_arr.length, @received_arr.length)
44
- end
45
- end
46
-
47
- end
48
- end
49
-
50
- context "using byte Strings" do
51
-
52
- setup do
53
- @messages = TestHelper::VariousMIDIByteStrMessages
54
- @messages_str = @messages.join
55
- @received_str = ""
56
- @pointer = 0
57
- end
58
-
59
- should "do IO" do
60
- TestHelper.device[:output].open do |output|
61
- TestHelper.device[:input].open do |input|
62
-
63
- @messages.each do |msg|
64
-
65
- $>.puts "sending: " + msg.inspect
66
-
67
- output.puts(msg)
68
- sleep(1)
69
- received = input.gets_bytestr.map { |m| m[:data] }.flatten.join
70
- $>.puts "received: " + received.inspect
71
-
72
- assert_equal(@messages_str.slice(@pointer, received.length), received)
73
- @pointer += received.length
74
- @received_str += received
75
- end
76
- assert_equal(@messages_str, @received_str)
77
-
78
- end
79
- end
80
-
81
-
82
- end
83
-
84
- end
85
-
86
- end
87
-
88
- end
89
-
90
- end