ffi-coremidi 0.4.1 → 0.5.0

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: 24583f1bb64dea16e2988a4ed7f4c51411000413
4
- data.tar.gz: 3d7804e408e78313e46095ca9fa879c1c427d9e0
2
+ SHA256:
3
+ metadata.gz: d05cb8f763c856b651e7fa5f94499350bc7576cd210e7402ce26bc9bbd714739
4
+ data.tar.gz: 77a98c6abc53d0287bc4e57d7f3cce217da9e32d73fd6a3205602f0c6bd69fbe
5
5
  SHA512:
6
- metadata.gz: c8d2c2fc9c502f21710213e46ecd03937a61f58f0f6bdbc74652ab3995c5615eb1ef23ebdf79a1fe0afaa8fecdd39898ae1ad29b257de5314b2a038f2ff6f688
7
- data.tar.gz: adbb7aa16fe70b8306cd0dd8f9740a15b1b23fd3c4b04ec61616120b3fcc3ad0e1e132c4a526d0cc682d0eb94067940c86f023654e457e01cc7e414033df57aa
6
+ metadata.gz: fc172a0d02c6fc6efd3d1337623e92fdf9bb4b01e08debe2105ed78bb306d49db44308d72cc0041cd04ee04ecb50f4ebda935610bcf18dab67afb2b90e1a5d9b
7
+ data.tar.gz: bbdcf6d8e87f2896db09859e79b6d8c39f33ea2046a10704d917439d7974e50224ed842414ece048e99d671943da7939e47cef74ae3e4683ee4ccdf54646687b
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?
@@ -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,
@@ -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,8 +1,8 @@
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
8
  # The buffer of received messages since instantiation
@@ -25,9 +25,9 @@ module CoreMIDI
25
25
  #
26
26
  # @return [Array<Hash>]
27
27
  def gets
28
- fill_buffer
28
+ fill_buffer(locking: true)
29
29
  end
30
- alias_method :read, :gets
30
+ alias read gets
31
31
 
32
32
  # Same as Source#gets except that it returns message data as string of hex
33
33
  # digits as such:
@@ -45,12 +45,12 @@ module CoreMIDI
45
45
  end
46
46
  messages
47
47
  end
48
- alias_method :gets_bytestr, :gets_s
48
+ alias gets_bytestr gets_s
49
49
 
50
50
  # Enable this the input for use; can be passed a block
51
51
  # @return [Source]
52
- def enable(options = {}, &block)
53
- @enabled = true unless @enabled
52
+ def enable(_options = {})
53
+ @enabled ||= true
54
54
  if block_given?
55
55
  begin
56
56
  yield(self)
@@ -60,20 +60,20 @@ module CoreMIDI
60
60
  end
61
61
  self
62
62
  end
63
- alias_method :open, :enable
64
- alias_method :start, :enable
63
+ alias open enable
64
+ alias start enable
65
65
 
66
66
  # Close this input
67
67
  # @return [Boolean]
68
68
  def close
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?
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?
77
77
  if @enabled
78
78
  @enabled = false
79
79
  true
@@ -102,14 +102,27 @@ module CoreMIDI
102
102
 
103
103
  protected
104
104
 
105
+ def truncate_buffer
106
+ @buffer.slice!(-1024, 1024)
107
+ end
108
+
105
109
  # Migrate new received messages from the callback queue to
106
110
  # the buffer
107
- def fill_buffer
111
+ def fill_buffer(locking: nil)
112
+ locking ||= false
113
+
108
114
  messages = []
109
- until @queue.empty?
110
- messages << @queue.pop
115
+
116
+ if locking && @queue.empty?
117
+ @threads_sync_semaphore.synchronize do
118
+ @threads_waiting << Thread.current
119
+ end
120
+ sleep
111
121
  end
122
+
123
+ messages << @queue.pop until @queue.empty?
112
124
  @buffer += messages
125
+ truncate_buffer
113
126
  @pointer = @buffer.length
114
127
  messages
115
128
  end
@@ -120,14 +133,14 @@ module CoreMIDI
120
133
  enable_client
121
134
  initialize_port
122
135
  @resource = API.MIDIEntityGetSource(@entity.resource, @resource_id)
123
- error = API.MIDIPortConnectSource(@handle, @resource, nil )
136
+ error = API.MIDIPortConnectSource(@handle, @resource, nil)
124
137
  initialize_buffer
125
138
  @queue = Queue.new
126
139
  @sysex_buffer = []
127
140
 
128
141
  error.zero?
129
142
  end
130
- alias_method :connect?, :connect
143
+ alias connect? connect
131
144
 
132
145
  private
133
146
 
@@ -145,33 +158,27 @@ module CoreMIDI
145
158
  end
146
159
  message = get_message_formatted(bytes, timestamp)
147
160
  @queue << message
148
- message
149
- end
150
161
 
151
- # New MIDI messages from the queue
152
- def queued_messages
153
- @queue.pop
154
- end
162
+ @threads_sync_semaphore.synchronize do
163
+ @threads_waiting.each(&:run)
164
+ @threads_waiting.clear
165
+ end
155
166
 
156
- # Are there new MIDI messages in the queue?
157
- def queued_messages?
158
- !@queue.empty?
167
+ message
159
168
  end
160
169
 
161
170
  # The callback fired by coremidi when new MIDI messages are received
162
171
  def get_event_callback
163
172
  Thread.abort_on_exception = true
164
- Proc.new do |new_packets, refCon_ptr, connRefCon_ptr|
165
- begin
166
- # p "packets received: #{new_packets[:numPackets]}"
167
- timestamp = Time.now.to_f
168
- messages = get_messages(new_packets)
169
- messages.each do |message|
170
- enqueue_message(message, timestamp)
171
- end
172
- rescue Exception => exception
173
- Thread.main.raise(exception)
173
+ proc do |new_packets, _refCon_ptr, _connRefCon_ptr|
174
+ # p "packets received: #{new_packets[:numPackets]}"
175
+ timestamp = Time.now.to_f
176
+ messages = get_messages(new_packets)
177
+ messages.each do |message|
178
+ enqueue_message(message, timestamp)
174
179
  end
180
+ rescue Exception => e
181
+ Thread.main.raise(e)
175
182
  end
176
183
  end
177
184
 
@@ -184,18 +191,18 @@ module CoreMIDI
184
191
  data = first[:data].to_a
185
192
  messages = []
186
193
  messages << data.slice!(0, first[:length])
187
- (count - 1).times do |i|
194
+ (count - 1).times do |_i|
188
195
  length_index = find_next_length_index(data)
189
196
  message_length = data[length_index]
190
- unless message_length.nil?
191
- packet_start_index = length_index + 2
192
- packet_end_index = packet_start_index + message_length
193
- if data.length >= packet_end_index + 1
194
- packet = data.slice!(0..packet_end_index)
195
- message = packet.slice(packet_start_index, message_length)
196
- messages << message
197
- end
198
- end
197
+ next if message_length.nil?
198
+
199
+ packet_start_index = length_index + 2
200
+ packet_end_index = packet_start_index + message_length
201
+ next unless data.length >= packet_end_index + 1
202
+
203
+ packet = data.slice!(0..packet_end_index)
204
+ message = packet.slice(packet_start_index, message_length)
205
+ messages << message
199
206
  end
200
207
  messages
201
208
  end
@@ -234,6 +241,7 @@ module CoreMIDI
234
241
  port = API.create_midi_input_port(@client, @resource_id, @name, @callback)
235
242
  @handle = port[:handle]
236
243
  raise "MIDIInputPortCreate returned error code #{port[:error]}" unless port[:error].zero?
244
+
237
245
  true
238
246
  end
239
247
 
@@ -248,7 +256,5 @@ module CoreMIDI
248
256
  end
249
257
  true
250
258
  end
251
-
252
259
  end
253
-
254
260
  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.4.1"
27
+ VERSION = '0.5.0'
26
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-coremidi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
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-07-06 00:00:00.000000000 Z
11
+ date: 2022-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -16,100 +16,100 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.5'
19
+ version: '5.15'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 5.5.0
22
+ version: 5.15.0
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: '5.15'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 5.5.0
32
+ version: 5.15.0
33
33
  - !ruby/object:Gem::Dependency
34
- name: mocha
34
+ name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.1'
39
+ version: '13.0'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 1.1.0
42
+ version: 13.0.6
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '1.1'
49
+ version: '13.0'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 1.1.0
52
+ version: 13.0.6
53
53
  - !ruby/object:Gem::Dependency
54
- name: rake
54
+ name: rspec
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '10.4'
59
+ version: '3.11'
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 10.4.2
62
+ version: 3.11.0
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '10.4'
69
+ version: '3.11'
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 10.4.2
72
+ version: 3.11.0
73
73
  - !ruby/object:Gem::Dependency
74
- name: shoulda-context
74
+ name: rubocop
75
75
  requirement: !ruby/object:Gem::Requirement
76
76
  requirements:
77
77
  - - "~>"
78
78
  - !ruby/object:Gem::Version
79
- version: '1.2'
79
+ version: '1.25'
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 1.2.1
82
+ version: 1.25.1
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.2'
89
+ version: '1.25'
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
- version: 1.2.1
92
+ version: 1.25.1
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: ffi
95
95
  requirement: !ruby/object:Gem::Requirement
96
96
  requirements:
97
97
  - - "~>"
98
98
  - !ruby/object:Gem::Version
99
- version: '1.9'
99
+ version: '1.15'
100
100
  - - ">="
101
101
  - !ruby/object:Gem::Version
102
- version: 1.9.6
102
+ version: 1.15.5
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '1.9'
109
+ version: '1.15'
110
110
  - - ">="
111
111
  - !ruby/object:Gem::Version
112
- version: 1.9.6
112
+ version: 1.15.5
113
113
  description: Perform realtime MIDI IO with Ruby for OSX
114
114
  email:
115
115
  - ari.russo@gmail.com
@@ -127,14 +127,11 @@ files:
127
127
  - lib/coremidi/entity.rb
128
128
  - lib/coremidi/source.rb
129
129
  - lib/coremidi/type_conversion.rb
130
- - test/helper.rb
131
- - test/input_buffer_test.rb
132
- - test/io_test.rb
133
130
  homepage: http://github.com/arirusso/ffi-coremidi
134
131
  licenses:
135
132
  - Apache-2.0
136
133
  metadata: {}
137
- post_install_message:
134
+ post_install_message:
138
135
  rdoc_options: []
139
136
  require_paths:
140
137
  - lib
@@ -149,9 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
146
  - !ruby/object:Gem::Version
150
147
  version: 1.3.6
151
148
  requirements: []
152
- rubyforge_project: ffi-coremidi
153
- rubygems_version: 2.6.12
154
- signing_key:
149
+ rubygems_version: 3.3.3
150
+ signing_key:
155
151
  specification_version: 4
156
152
  summary: Realtime MIDI IO with Ruby for OSX
157
153
  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