ffi-coremidi 0.3.9 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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