ffi-coremidi 0.3.8 → 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 +5 -5
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/coremidi/api.rb +45 -51
- data/lib/coremidi/destination.rb +17 -19
- data/lib/coremidi/device.rb +20 -22
- data/lib/coremidi/endpoint.rb +11 -10
- data/lib/coremidi/entity.rb +31 -39
- data/lib/coremidi/source.rb +82 -67
- data/lib/coremidi/type_conversion.rb +8 -9
- data/lib/coremidi.rb +17 -12
- metadata +30 -34
- data/test/helper.rb +0 -66
- data/test/input_buffer_test.rb +0 -42
- data/test/io_test.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d05cb8f763c856b651e7fa5f94499350bc7576cd210e7402ce26bc9bbd714739
|
4
|
+
data.tar.gz: 77a98c6abc53d0287bc4e57d7f3cce217da9e32d73fd6a3205602f0c6bd69fbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc172a0d02c6fc6efd3d1337623e92fdf9bb4b01e08debe2105ed78bb306d49db44308d72cc0041cd04ee04ecb50f4ebda935610bcf18dab67afb2b90e1a5d9b
|
7
|
+
data.tar.gz: bbdcf6d8e87f2896db09859e79b6d8c39f33ea2046a10704d917439d7974e50224ed842414ece048e99d671943da7939e47cef74ae3e4683ee4ccdf54646687b
|
data/LICENSE
CHANGED
data/README.md
CHANGED
data/lib/coremidi/api.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
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 =
|
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
|
-
:
|
71
|
-
:
|
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
|
-
:
|
82
|
-
:
|
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
|
-
:
|
93
|
-
:
|
88
|
+
error: error,
|
89
|
+
handle: handle
|
94
90
|
}
|
95
91
|
end
|
96
92
|
|
@@ -100,17 +96,18 @@ module CoreMIDI
|
|
100
96
|
packet_ptr = API.MIDIPacketListInit(packet_list)
|
101
97
|
time = HostTime.AudioGetCurrentHostTime
|
102
98
|
packet_ptr = if X86_64
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
|
111
108
|
# @param [FFI::Pointer] resource A pointer to an underlying struct
|
112
109
|
# @param [String, Symbol] name The property name to get
|
113
|
-
# @return [
|
110
|
+
# @return [Integer]
|
114
111
|
def self.get_int(resource, name)
|
115
112
|
property = API::CF.CFStringCreateWithCString(nil, name.to_s, 0)
|
116
113
|
value = FFI::MemoryPointer.new(:pointer, 32)
|
@@ -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(
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
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, [
|
216
|
+
attach_function :MIDIPacketListAdd, %i[pointer int pointer uint64 int pointer], :pointer
|
219
217
|
else
|
220
|
-
attach_function :MIDIPacketListAdd, [
|
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, [
|
227
|
+
enum :CFStringEncoding, [:kCFStringEncodingUTF8, 0x08000100]
|
231
228
|
|
232
229
|
# CFString* CFStringCreateWithCString( ?, CString, encoding)
|
233
|
-
attach_function :CFStringCreateWithCString, [
|
230
|
+
attach_function :CFStringCreateWithCString, %i[pointer string int], :pointer
|
234
231
|
# CString* CFStringGetCStringPtr(CFString*, encoding)
|
235
|
-
attach_function :CFStringGetCStringPtr, [
|
232
|
+
attach_function :CFStringGetCStringPtr, %i[pointer int], :pointer
|
236
233
|
|
237
234
|
# CFIndex CFStringGetLength(CFStringRef theString);
|
238
|
-
attach_function :CFStringGetLength, [
|
235
|
+
attach_function :CFStringGetLength, [:CFStringRef], :CFIndex
|
239
236
|
|
240
237
|
# CFIndex CFStringGetMaximumSizeForEncoding(CFIndex length, CFStringEncoding encoding);
|
241
|
-
attach_function :CFStringGetMaximumSizeForEncoding, [
|
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, [
|
241
|
+
attach_function :CFStringGetCString, %i[CFStringRef pointer CFIndex CFStringEncoding], :bool
|
245
242
|
|
246
243
|
# void CFRelease (CFTypeRef cf);
|
247
|
-
attach_function :CFRelease, [
|
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
|
data/lib/coremidi/destination.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
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,41 +24,41 @@ 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
|
-
|
34
|
-
|
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
|
-
# @param [*
|
37
|
+
# @param [*Integer] data Numeric bytes eg 0x90, 0x40, 0x40
|
38
38
|
# @return [Boolean]
|
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
|
42
|
+
send("puts_#{type}", bytes, data.size)
|
43
43
|
true
|
44
44
|
end
|
45
45
|
|
46
46
|
# Send a MIDI message of indeterminate type
|
47
|
-
# @param [*Array<
|
47
|
+
# @param [*Array<Integer>, *Array<String>, *Integer, *String] args
|
48
48
|
# @return [Boolean]
|
49
49
|
def puts(*args)
|
50
50
|
case args.first
|
51
51
|
when Array then args.each { |arg| puts(*arg) }
|
52
|
-
when
|
52
|
+
when Integer then puts_bytes(*args)
|
53
53
|
when String then puts_bytestr(*args)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
alias write puts
|
57
57
|
|
58
58
|
# Enable this device
|
59
59
|
# @return [Destination]
|
60
|
-
def enable(
|
61
|
-
@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
|
-
|
72
|
-
|
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(
|
100
|
+
@resource = API.MIDIEntityGetDestination(@entity.resource, @resource_id)
|
101
101
|
!@resource.address.zero? && client_error.zero? && port_error.zero?
|
102
102
|
end
|
103
|
-
|
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
|
-
|
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
|
data/lib/coremidi/device.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
#
|
3
|
+
module CoreMIDI
|
4
|
+
# A MIDI device may have multiple logically distinct sub-components. For example, one device may
|
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
|
13
13
|
|
14
|
-
# @param [
|
14
|
+
# @param [Integer] id The ID for the device
|
15
15
|
# @param [Object] device_pointer The underlying device pointer
|
16
16
|
# @param [Hash] options
|
17
17
|
# @option options [Boolean] :include_offline Whether to include offline entities (default: false)
|
@@ -21,20 +21,20 @@ module CoreMIDI
|
|
21
21
|
@entities = []
|
22
22
|
populate(options)
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# Endpoints for this device
|
26
26
|
# @return [Array<Endpoint>]
|
27
27
|
def endpoints
|
28
|
-
endpoints = { :
|
29
|
-
endpoints.
|
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
|
33
33
|
endpoints
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Assign all of this Device's endpoints an consecutive local id
|
37
|
-
# @param [Integer] last_id The highest already used endpoint ID
|
37
|
+
# @param [Integer] last_id The highest already used endpoint ID
|
38
38
|
# @return [Integer] The highest used endpoint ID after populating this device's endpoints
|
39
39
|
def populate_endpoint_ids(last_id)
|
40
40
|
id = 0
|
@@ -53,8 +53,8 @@ module CoreMIDI
|
|
53
53
|
if !populated? || !use_cache
|
54
54
|
@devices = []
|
55
55
|
counter = 0
|
56
|
-
|
57
|
-
device = new(counter, device_pointer, :
|
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
|
@@ -72,17 +72,17 @@ module CoreMIDI
|
|
72
72
|
|
73
73
|
# Has the device list been populated?
|
74
74
|
def self.populated?
|
75
|
-
!@devices.nil? && !@devices.empty?
|
75
|
+
!@devices.nil? && !@devices.empty?
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
79
79
|
|
80
80
|
# Populate the device name
|
81
81
|
def populate_name
|
82
|
-
@name = API.get_string(@resource,
|
83
|
-
raise
|
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
|
87
87
|
def self.populate_endpoint_ids
|
88
88
|
counter = 0
|
@@ -93,12 +93,12 @@ module CoreMIDI
|
|
93
93
|
# Populates the entities for this device. These entities are in turn used to gather the endpoints.
|
94
94
|
# @param [Hash] options
|
95
95
|
# @option options [Boolean] :include_offline Whether to include offline entities (default: false)
|
96
|
-
# @return [
|
96
|
+
# @return [Integer] The number of entities populated
|
97
97
|
def populate_entities(options = {})
|
98
98
|
include_if_offline = options[:include_offline] || false
|
99
99
|
i = 0
|
100
|
-
|
101
|
-
@entities << Entity.new(entity_pointer, :
|
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(:
|
110
|
+
populate_entities(include_offline: options[:include_offline])
|
111
111
|
end
|
112
|
-
|
113
112
|
end
|
114
|
-
|
115
113
|
end
|
data/lib/coremidi/endpoint.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
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,15 +15,18 @@ module CoreMIDI
|
|
15
15
|
|
16
16
|
def_delegators :entity, :manufacturer, :model, :name
|
17
17
|
|
18
|
-
|
18
|
+
alias enabled? enabled
|
19
19
|
|
20
|
-
# @param [
|
20
|
+
# @param [Integer] resource_id
|
21
21
|
# @param [Entity] entity
|
22
22
|
def initialize(resource_id, entity)
|
23
23
|
@entity = entity
|
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?
|
@@ -33,8 +36,8 @@ module CoreMIDI
|
|
33
36
|
end
|
34
37
|
|
35
38
|
# Set the id for this endpoint (the id is immutable)
|
36
|
-
# @param [
|
37
|
-
# @return [
|
39
|
+
# @param [Integer] val
|
40
|
+
# @return [Integer]
|
38
41
|
def id=(id)
|
39
42
|
@id ||= id
|
40
43
|
end
|
@@ -67,8 +70,8 @@ module CoreMIDI
|
|
67
70
|
# @return [Hash]
|
68
71
|
def self.all_by_type
|
69
72
|
{
|
70
|
-
:
|
71
|
-
:
|
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
|