Module: MIDICommunicationsMacOS::API

Extended by:
FFI::Library
Defined in:
lib/midi-communications-macos/api.rb

Overview

Coremidi C binding

Defined Under Namespace

Modules: CF, HostTime Classes: MIDIPacket, MIDIPacketList, MIDISysexSendRequest

Constant Summary collapse

X86_64 =

if osx is 10.6 or higher, there are some differences with 32 vs 64 bit handling

`uname -r`.scan(/\d*\.\d*/).first.to_f >= 10.6

Class Method Summary collapse

Class Method Details

.create_midi_client(resource_id, name) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/midi-communications-macos/api.rb', line 62

def self.create_midi_client(resource_id, name)
  client_name = API::CF.CFStringCreateWithCString(nil, "Client #{resource_id} #{name}", 0)
  client_pointer = FFI::MemoryPointer.new(:pointer)
  error = API.MIDIClientCreate(client_name, nil, nil, client_pointer)
  client = client_pointer.read_pointer
  {
    error: error,
    resource: client
  }
end

.create_midi_input_port(client, resource_id, name, callback) ⇒ Object



73
74
75
76
77
78
79
80
81
82
# File 'lib/midi-communications-macos/api.rb', line 73

def self.create_midi_input_port(client, resource_id, name, callback)
  port_name = API::CF.CFStringCreateWithCString(nil, "Port #{resource_id}: #{name}", 0)
  handle_ptr = FFI::MemoryPointer.new(:pointer)
  error = API.MIDIInputPortCreate(client, port_name, callback, nil, handle_ptr)
  handle = handle_ptr.read_pointer
  {
    error: error,
    handle: handle
  }
end

.create_midi_output_port(client, resource_id, name) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/midi-communications-macos/api.rb', line 84

def self.create_midi_output_port(client, resource_id, name)
  port_name = CF.CFStringCreateWithCString(nil, "Port #{resource_id}: #{name}", 0)
  port_pointer = FFI::MemoryPointer.new(:pointer)
  error = API.MIDIOutputPortCreate(client, port_name, port_pointer)
  handle = port_pointer.read_pointer
  {
    error: error,
    handle: handle
  }
end

.get_callback(*args, &block) ⇒ Object



48
49
50
# File 'lib/midi-communications-macos/api.rb', line 48

def self.get_callback(*args, &block)
  FFI::Function.new(:void, *args, &block)
end

.get_int(resource, name) ⇒ Integer

Parameters:

  • resource (FFI::Pointer)

    A pointer to an underlying struct

  • name (String, Symbol)

    The property name to get

Returns:

  • (Integer)


112
113
114
115
116
117
# File 'lib/midi-communications-macos/api.rb', line 112

def self.get_int(resource, name)
  property = API::CF.CFStringCreateWithCString(nil, name.to_s, 0)
  value = FFI::MemoryPointer.new(:pointer, 32)
  API::MIDIObjectGetIntegerProperty(resource, property, value)
  value.read_int
end

.get_midi_packet(data) ⇒ Object

Pack the given data into a midi-communications-macos MIDI packet (used by Destination)



53
54
55
56
57
58
59
60
# File 'lib/midi-communications-macos/api.rb', line 53

def self.get_midi_packet(data)
  format = 'C' * data.size
  packed_data = data.pack(format)
  char_size = FFI.type_size(:char) * data.size
  bytes = FFI::MemoryPointer.new(char_size)
  bytes.write_string(packed_data)
  bytes
end

.get_midi_packet_list(bytes, size) ⇒ Object

(used by Destination)



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/midi-communications-macos/api.rb', line 96

def self.get_midi_packet_list(bytes, size)
  packet_list = FFI::MemoryPointer.new(256)
  packet_ptr = API.MIDIPacketListInit(packet_list)
  time = HostTime.AudioGetCurrentHostTime
  if X86_64
    API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time, size, bytes)
  else
    # Pass in two 32-bit 0s for the 64 bit time
    API.MIDIPacketListAdd(packet_list, 256, packet_ptr, time >> 32, time & 0xFFFFFFFF, size, bytes)
  end
  packet_list
end

.get_string(resource, name) ⇒ String

Parameters:

  • resource (FFI::Pointer)

    A pointer to an underlying struct

  • name (String, Symbol)

    The property name to get

Returns:

  • (String)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/midi-communications-macos/api.rb', line 122

def self.get_string(resource, name)
  property = CF.CFStringCreateWithCString(nil, name.to_s, 0)
  begin
    pointer = FFI::MemoryPointer.new(:pointer)
    MIDIObjectGetStringProperty(resource, property, pointer)
    string = pointer.read_pointer
    length = CF.CFStringGetMaximumSizeForEncoding(CF.CFStringGetLength(string), :kCFStringEncodingUTF8)

    bytes = FFI::MemoryPointer.new(length + 1)

    if CF.CFStringGetCString(string, bytes, length + 1, :kCFStringEncodingUTF8)
      bytes.read_string.force_encoding('utf-8')
    end
  ensure
    CF.CFRelease(string) unless string.nil? || string.null?
    CF.CFRelease(property) unless property.null?
  end
end