ffi-coremidi 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +4 -4
- data/lib/coremidi.rb +2 -2
- data/lib/coremidi/destination.rb +16 -18
- data/lib/coremidi/endpoint.rb +10 -8
- data/lib/coremidi/source.rb +15 -17
- data/test/helper.rb +21 -13
- data/test/input_buffer_test.rb +4 -4
- data/test/io_test.rb +5 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28b485379651851b48abf76f539672cdc9f08a97
|
4
|
+
data.tar.gz: 66eb8e0c88b90cd4ef8eaa3547964d5043266a9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42e781c9108831e86ec68f04d9873ace1d45c1d093195bc24207e9a5e4cd8f331da8bec8c37659152422e7d3ff184f081463048e6c92308ebc25af62c7a3d0a6
|
7
|
+
data.tar.gz: f1cf748819e912dabb989495fc2359d0c26593a20e4dcb1aa5cf57605f61bcc2e172f53630f87e70f571c064b911991e826e50d199af9f80c60b2d561da0aa18
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Note that in the interest of allowing people on other platforms to utilize your
|
|
12
12
|
* Input and output on multiple devices concurrently
|
13
13
|
* Generalized handling of different MIDI Message types (including SysEx)
|
14
14
|
* Timestamped input events
|
15
|
-
* Patch MIDI via software to other programs using IAC
|
15
|
+
* Patch MIDI via software to other programs using IAC
|
16
16
|
|
17
17
|
### Requirements
|
18
18
|
|
@@ -23,11 +23,11 @@ Note that in the interest of allowing people on other platforms to utilize your
|
|
23
23
|
If you're using Bundler, add this line to your application's Gemfile:
|
24
24
|
|
25
25
|
`gem "ffi-coremidi"`
|
26
|
-
|
26
|
+
|
27
27
|
Otherwise
|
28
28
|
|
29
29
|
`gem install ffi-coremidi`
|
30
|
-
|
30
|
+
|
31
31
|
### Documentation
|
32
32
|
|
33
33
|
[rdoc](http://rubydoc.info/github/arirusso/ffi-coremidi)
|
@@ -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-
|
51
|
+
Copyright (c) 2011-2015 [Ari Russo](http://github.com/arirusso)
|
data/lib/coremidi.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ffi-coremidi
|
2
2
|
#
|
3
3
|
# Realtime MIDI IO with Ruby for OSX
|
4
|
-
# (c)2011-
|
4
|
+
# (c)2011-2015 Ari Russo
|
5
5
|
|
6
6
|
# libs
|
7
7
|
require "ffi"
|
@@ -19,5 +19,5 @@ require "coremidi/source"
|
|
19
19
|
require "coremidi/destination"
|
20
20
|
|
21
21
|
module CoreMIDI
|
22
|
-
VERSION = "0.3.
|
22
|
+
VERSION = "0.3.6"
|
23
23
|
end
|
data/lib/coremidi/destination.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module CoreMIDI
|
2
2
|
|
3
|
-
#
|
3
|
+
# Type of endpoint used for output
|
4
4
|
class Destination
|
5
5
|
|
6
6
|
include Endpoint
|
@@ -23,9 +23,9 @@ module CoreMIDI
|
|
23
23
|
# @return [Boolean]
|
24
24
|
def puts_s(data)
|
25
25
|
data = data.dup
|
26
|
-
|
26
|
+
bytes = []
|
27
27
|
until (str = data.slice!(0,2)).eql?("")
|
28
|
-
|
28
|
+
bytes << str.hex
|
29
29
|
end
|
30
30
|
puts_bytes(*bytes)
|
31
31
|
true
|
@@ -47,10 +47,10 @@ module CoreMIDI
|
|
47
47
|
# @param [*Array<Fixnum>, *Array<String>, *Fixnum, *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
|
-
|
53
|
-
|
52
|
+
when Fixnum then puts_bytes(*args)
|
53
|
+
when String then puts_bytestr(*args)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
alias_method :write, :puts
|
@@ -58,14 +58,12 @@ module CoreMIDI
|
|
58
58
|
# Enable this device
|
59
59
|
# @return [Destination]
|
60
60
|
def enable(options = {}, &block)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
close
|
68
|
-
end
|
61
|
+
@enabled = true unless @enabled
|
62
|
+
if block_given?
|
63
|
+
begin
|
64
|
+
yield(self)
|
65
|
+
ensure
|
66
|
+
close
|
69
67
|
end
|
70
68
|
end
|
71
69
|
self
|
@@ -78,7 +76,7 @@ module CoreMIDI
|
|
78
76
|
def self.first
|
79
77
|
Endpoint.first(:destination)
|
80
78
|
end
|
81
|
-
|
79
|
+
|
82
80
|
# Shortcut to the last output endpoint available
|
83
81
|
# @return [Destination]
|
84
82
|
def self.last
|
@@ -90,7 +88,7 @@ module CoreMIDI
|
|
90
88
|
def self.all
|
91
89
|
Endpoint.all_by_type[:destination]
|
92
90
|
end
|
93
|
-
|
91
|
+
|
94
92
|
protected
|
95
93
|
|
96
94
|
# Base initialization for this endpoint -- done whether or not the endpoint is enabled to
|
@@ -128,9 +126,9 @@ module CoreMIDI
|
|
128
126
|
|
129
127
|
SysexCompletionCallback =
|
130
128
|
API.get_callback([:pointer]) do |sysex_request_ptr|
|
131
|
-
|
129
|
+
# this isn't working for some reason. as of now, it's not needed though
|
132
130
|
end
|
133
|
-
|
131
|
+
|
134
132
|
# Initialize a coremidi port for this endpoint
|
135
133
|
def initialize_port
|
136
134
|
port = API.create_midi_output_port(@client, @resource_id, @name)
|
data/lib/coremidi/endpoint.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
module CoreMIDI
|
2
2
|
|
3
|
-
# A
|
3
|
+
# A source or destination of a 16-channel MIDI stream
|
4
|
+
#
|
5
|
+
# https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/Reference/reference.html
|
4
6
|
module Endpoint
|
5
|
-
|
7
|
+
|
6
8
|
extend Forwardable
|
7
9
|
|
8
10
|
attr_reader :enabled, # has the endpoint been initialized?
|
@@ -10,7 +12,7 @@ module CoreMIDI
|
|
10
12
|
:id,
|
11
13
|
:resource_id, # :input or :output
|
12
14
|
:type
|
13
|
-
|
15
|
+
|
14
16
|
def_delegators :entity, :manufacturer, :model, :name
|
15
17
|
|
16
18
|
alias_method :enabled?, :enabled
|
@@ -23,13 +25,13 @@ module CoreMIDI
|
|
23
25
|
@type = get_type
|
24
26
|
@enabled = false
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
# Is this endpoint online?
|
28
30
|
# @return [Boolean]
|
29
31
|
def online?
|
30
32
|
@entity.online? && connect?
|
31
33
|
end
|
32
|
-
|
34
|
+
|
33
35
|
# Set the id for this endpoint (the id is immutable)
|
34
36
|
# @param [Fixnum] val
|
35
37
|
# @return [Fixnum]
|
@@ -83,9 +85,9 @@ module CoreMIDI
|
|
83
85
|
case type
|
84
86
|
when :source then Source
|
85
87
|
when :destination then Destination
|
86
|
-
end
|
88
|
+
end
|
87
89
|
end
|
88
|
-
|
90
|
+
|
89
91
|
protected
|
90
92
|
|
91
93
|
# Constructs the endpoint type (eg source, destination) for easy consumption
|
@@ -93,7 +95,7 @@ module CoreMIDI
|
|
93
95
|
class_name = self.class.name.split('::').last
|
94
96
|
class_name.downcase.to_sym
|
95
97
|
end
|
96
|
-
|
98
|
+
|
97
99
|
# Enables the coremidi MIDI client that will go with this endpoint
|
98
100
|
def enable_client
|
99
101
|
client = API.create_midi_client(@resource_id, @name)
|
data/lib/coremidi/source.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module CoreMIDI
|
2
2
|
|
3
|
-
#
|
3
|
+
# Type of endpoint used for input
|
4
4
|
class Source
|
5
5
|
|
6
6
|
include Endpoint
|
@@ -30,7 +30,7 @@ module CoreMIDI
|
|
30
30
|
end
|
31
31
|
alias_method :read, :gets
|
32
32
|
|
33
|
-
# Same as Source#gets except that it returns message data as string of hex
|
33
|
+
# Same as Source#gets except that it returns message data as string of hex
|
34
34
|
# digits as such:
|
35
35
|
# [
|
36
36
|
# { :data => "904060", :timestamp => 904 },
|
@@ -41,7 +41,7 @@ module CoreMIDI
|
|
41
41
|
# @return [Array<Hash>]
|
42
42
|
def gets_s
|
43
43
|
messages = gets
|
44
|
-
messages.each do |message|
|
44
|
+
messages.each do |message|
|
45
45
|
message[:data] = TypeConversion.numeric_bytes_to_hex_string(message[:data])
|
46
46
|
end
|
47
47
|
messages
|
@@ -51,14 +51,12 @@ module CoreMIDI
|
|
51
51
|
# Enable this the input for use; can be passed a block
|
52
52
|
# @return [Source]
|
53
53
|
def enable(options = {}, &block)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
close
|
61
|
-
end
|
54
|
+
@enabled = true unless @enabled
|
55
|
+
if block_given?
|
56
|
+
begin
|
57
|
+
yield(self)
|
58
|
+
ensure
|
59
|
+
close
|
62
60
|
end
|
63
61
|
end
|
64
62
|
self
|
@@ -105,9 +103,9 @@ module CoreMIDI
|
|
105
103
|
|
106
104
|
protected
|
107
105
|
|
108
|
-
# Base initialization for this endpoint -- done whether or not the endpoint is enabled to check whether
|
106
|
+
# Base initialization for this endpoint -- done whether or not the endpoint is enabled to check whether
|
109
107
|
# it is truly available for use
|
110
|
-
def connect
|
108
|
+
def connect
|
111
109
|
enable_client
|
112
110
|
initialize_port
|
113
111
|
@resource = API.MIDIEntityGetSource(@entity.resource, @resource_id)
|
@@ -134,7 +132,7 @@ module CoreMIDI
|
|
134
132
|
@sysex_buffer.clear
|
135
133
|
end
|
136
134
|
end
|
137
|
-
@buffer << get_message_formatted(bytes, timestamp) if @sysex_buffer.empty?
|
135
|
+
@buffer << get_message_formatted(bytes, timestamp) if @sysex_buffer.empty?
|
138
136
|
@buffer
|
139
137
|
end
|
140
138
|
|
@@ -214,9 +212,9 @@ module CoreMIDI
|
|
214
212
|
# Give a message its timestamp and package it in a Hash
|
215
213
|
# @return [Hash]
|
216
214
|
def get_message_formatted(raw, time)
|
217
|
-
{
|
218
|
-
:data => raw,
|
219
|
-
:timestamp => timestamp(time)
|
215
|
+
{
|
216
|
+
:data => raw,
|
217
|
+
:timestamp => timestamp(time)
|
220
218
|
}
|
221
219
|
end
|
222
220
|
|
data/test/helper.rb
CHANGED
@@ -1,41 +1,49 @@
|
|
1
1
|
dir = File.dirname(File.expand_path(__FILE__))
|
2
2
|
$LOAD_PATH.unshift dir + "/../lib"
|
3
3
|
|
4
|
-
require "
|
4
|
+
require "minitest/autorun"
|
5
5
|
require "mocha/test_unit"
|
6
6
|
require "shoulda-context"
|
7
|
+
|
7
8
|
require "coremidi"
|
8
9
|
|
9
10
|
module TestHelper
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def device
|
15
|
+
@device ||= select_devices
|
16
|
+
end
|
17
|
+
|
18
|
+
def select_devices
|
19
|
+
@device ||= {}
|
13
20
|
{ :input => CoreMIDI::Source.all, :output => CoreMIDI::Destination.all }.each do |type, devs|
|
14
21
|
puts ""
|
15
22
|
puts "select an #{type.to_s}..."
|
16
|
-
while
|
23
|
+
while @device[type].nil?
|
17
24
|
devs.each do |device|
|
18
25
|
puts "#{device.id}: #{device.name}"
|
19
26
|
end
|
20
27
|
selection = $stdin.gets.chomp
|
21
28
|
if selection != ""
|
22
29
|
selection = selection.to_i
|
23
|
-
|
24
|
-
puts "selected #{selection} for #{type.to_s}" unless
|
30
|
+
@device[type] = devs.find { |d| d.id == selection }
|
31
|
+
puts "selected #{selection} for #{type.to_s}" unless @device[type]
|
25
32
|
end
|
26
33
|
end
|
27
34
|
end
|
28
|
-
|
29
|
-
|
35
|
+
@device
|
36
|
+
end
|
37
|
+
|
30
38
|
def bytestrs_to_ints(arr)
|
31
39
|
data = arr.map { |m| m[:data] }.join
|
32
40
|
output = []
|
33
41
|
until (bytestr = data.slice!(0,2)).eql?("")
|
34
42
|
output << bytestr.hex
|
35
43
|
end
|
36
|
-
output
|
44
|
+
output
|
37
45
|
end
|
38
|
-
|
46
|
+
|
39
47
|
# some MIDI messages
|
40
48
|
VariousMIDIMessages = [
|
41
49
|
[0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7], # SysEx
|
@@ -45,14 +53,14 @@ module TestHelper
|
|
45
53
|
[0x90, 60, 100], # note on
|
46
54
|
[0x80, 100, 100] # note off
|
47
55
|
]
|
48
|
-
|
56
|
+
|
49
57
|
# some MIDI messages
|
50
58
|
VariousMIDIByteStrMessages = [
|
51
59
|
"F04110421240007F0041F7", # SysEx
|
52
60
|
"906440", # note on
|
53
61
|
"804340" # note off
|
54
62
|
]
|
55
|
-
|
63
|
+
|
56
64
|
end
|
57
65
|
|
58
66
|
TestHelper.select_devices
|
data/test/input_buffer_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "helper"
|
2
2
|
|
3
|
-
class InputBufferTest < Test
|
3
|
+
class InputBufferTest < Minitest::Test
|
4
4
|
|
5
5
|
context "CoreMIDI" do
|
6
6
|
|
@@ -16,8 +16,8 @@ class InputBufferTest < Test::Unit::TestCase
|
|
16
16
|
@received_arr = []
|
17
17
|
@pointer = 0
|
18
18
|
|
19
|
-
@output =
|
20
|
-
@input =
|
19
|
+
@output = TestHelper.device[:output].open
|
20
|
+
@input = TestHelper.device[:input].open
|
21
21
|
@input.buffer.clear
|
22
22
|
end
|
23
23
|
|
@@ -26,7 +26,7 @@ class InputBufferTest < Test::Unit::TestCase
|
|
26
26
|
@messages.each do |message|
|
27
27
|
puts "sending: #{message.inspect}"
|
28
28
|
@output.puts(message)
|
29
|
-
bytes += message
|
29
|
+
bytes += message
|
30
30
|
|
31
31
|
sleep(0.5)
|
32
32
|
|
data/test/io_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "helper"
|
2
2
|
|
3
|
-
class CoreMIDI::IOTest < Test
|
3
|
+
class CoreMIDI::IOTest < Minitest::Test
|
4
4
|
|
5
5
|
# ** these tests assume that TestOutput is connected to TestInput
|
6
6
|
context "CoreMIDI" do
|
@@ -21,8 +21,8 @@ class CoreMIDI::IOTest < Test::Unit::TestCase
|
|
21
21
|
end
|
22
22
|
|
23
23
|
should "do IO" do
|
24
|
-
|
25
|
-
|
24
|
+
TestHelper.device[:output].open do |output|
|
25
|
+
TestHelper.device[:input].open do |input|
|
26
26
|
|
27
27
|
input.buffer.clear
|
28
28
|
|
@@ -57,8 +57,8 @@ class CoreMIDI::IOTest < Test::Unit::TestCase
|
|
57
57
|
end
|
58
58
|
|
59
59
|
should "do IO" do
|
60
|
-
|
61
|
-
|
60
|
+
TestHelper.device[:output].open do |output|
|
61
|
+
TestHelper.device[:input].open do |input|
|
62
62
|
|
63
63
|
@messages.each do |msg|
|
64
64
|
|
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.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ari Russo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|