unimidi 0.3.5 → 0.4.4
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 +3 -3
- data/lib/unimidi.rb +16 -26
- data/lib/unimidi/adapter/alsa-rawmidi.rb +22 -17
- data/lib/unimidi/adapter/ffi-coremidi.rb +21 -25
- data/lib/unimidi/adapter/midi-jruby.rb +21 -16
- data/lib/unimidi/adapter/midi-winmm.rb +21 -16
- data/lib/unimidi/command.rb +26 -0
- data/lib/unimidi/device.rb +182 -0
- data/lib/unimidi/input.rb +113 -0
- data/lib/unimidi/loader.rb +30 -0
- data/lib/unimidi/output.rb +63 -0
- data/lib/unimidi/platform.rb +11 -10
- data/lib/unimidi/type_conversion.rb +1 -1
- data/test/adapter_test.rb +70 -0
- data/test/class_methods_test.rb +99 -0
- data/test/functional_test.rb +128 -0
- data/test/helper.rb +20 -25
- data/test/input_test.rb +46 -0
- data/test/platform_test.rb +41 -23
- data/test/type_conversion_test.rb +14 -6
- metadata +16 -11
- data/lib/unimidi/congruous_api_adapter.rb +0 -321
- data/test/congruous_api_adapter_test.rb +0 -36
- data/test/input_buffer_test.rb +0 -40
- data/test/io_test.rb +0 -115
- data/test/selectors_test.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a75ecec80f113f9831ddabe50fbb3a00e183faae
|
4
|
+
data.tar.gz: 174c3ec107b0d696f8780708c83a9abf8a1e33ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1b430c23cb93b0373834bab0c66a25286dc5ca6bcee99e963b3d40892781f7b076b00a13ada2828bc871d035706d63d2fa774e101a4c965df1b28ea05bcc5e3
|
7
|
+
data.tar.gz: cae4027fefcbb3b0a06cebbe1eefba944b7ca55419fc025cf752f1604915ce19845a70290aeae3cd941491c30b8dc5b53b4ffb7681235221356be95d0d7fa195
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -9,14 +9,14 @@ Also see [MicroMIDI](http://github.com/arirusso/micromidi) which builds a full M
|
|
9
9
|
* Supports Linux, JRuby, OSX, Windows and Cygwin
|
10
10
|
* No compilation required
|
11
11
|
* Both input and output to and from multiple devices concurrently
|
12
|
-
*
|
12
|
+
* Generalized handling of different MIDI and SysEx Message types
|
13
13
|
* (OSX Only) Use IAC to internally route MIDI to other programs
|
14
14
|
|
15
15
|
### Requirements
|
16
16
|
|
17
17
|
Using Ruby 1.9.2 or JRuby 1.6.1 (or newer) is strongly recommended. JRuby should be run in 1.9 mode where applicable
|
18
18
|
|
19
|
-
UniMIDI uses one of the following libraries, depending on which platform you're using it on. The necessary library should install automatically with the unimidi gem.
|
19
|
+
UniMIDI uses one of the following libraries, depending on which platform you're using it on. The necessary library should install automatically with the unimidi gem.
|
20
20
|
|
21
21
|
Platform
|
22
22
|
|
@@ -84,4 +84,4 @@ See below for additional notes on testing with JRuby
|
|
84
84
|
|
85
85
|
Apache 2.0, See the file LICENSE
|
86
86
|
|
87
|
-
Copyright (c) 2010-
|
87
|
+
Copyright (c) 2010-2014 Ari Russo
|
data/lib/unimidi.rb
CHANGED
@@ -1,34 +1,24 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
# libs
|
10
|
-
require "forwardable"
|
11
|
-
require "singleton"
|
1
|
+
#
|
2
|
+
# Realtime MIDI IO for Ruby
|
3
|
+
#
|
4
|
+
# (c)2010-2014 Ari Russo and licensed under the Apache 2.0 License
|
5
|
+
#
|
12
6
|
|
13
7
|
# modules
|
14
|
-
require "unimidi/
|
8
|
+
require "unimidi/command"
|
9
|
+
require "unimidi/device"
|
10
|
+
require "unimidi/loader"
|
11
|
+
require "unimidi/platform"
|
15
12
|
require "unimidi/type_conversion"
|
16
13
|
|
17
14
|
# classes
|
18
|
-
require "unimidi/
|
15
|
+
require "unimidi/input"
|
16
|
+
require "unimidi/output"
|
19
17
|
|
20
18
|
module UniMIDI
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
puts "input:"
|
27
|
-
Input.list
|
28
|
-
puts "output:"
|
29
|
-
Output.list
|
30
|
-
else
|
31
|
-
raise "Command #{command.to_s} not found"
|
32
|
-
end
|
33
|
-
end
|
19
|
+
|
20
|
+
VERSION = "0.4.4"
|
21
|
+
|
22
|
+
Platform.bootstrap
|
23
|
+
|
34
24
|
end
|
@@ -1,25 +1,30 @@
|
|
1
|
-
require
|
1
|
+
require "alsa-rawmidi"
|
2
2
|
|
3
3
|
module UniMIDI
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
# Load underlying devices using the alsa-rawmidi gem
|
8
|
+
module AlsaRawMIDI
|
9
|
+
|
10
|
+
module Loader
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# @return [Array<AlsaRawMIDI::Input>]
|
15
|
+
def inputs
|
16
|
+
::AlsaRawMIDI::Device.all_by_type[:input]
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<AlsaRawMIDI::Output>]
|
20
|
+
def outputs
|
21
|
+
::AlsaRawMIDI::Device.all_by_type[:output]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
11
25
|
|
12
|
-
class Output < CongruousApiOutput
|
13
|
-
defer_to AlsaRawMIDI::Output
|
14
|
-
device_class AlsaRawMIDI::Device
|
15
|
-
end
|
16
|
-
|
17
|
-
class Device < CongruousApiDevice
|
18
|
-
defer_to AlsaRawMIDI::Device
|
19
|
-
input_class Input
|
20
|
-
output_class Output
|
21
26
|
end
|
22
|
-
|
27
|
+
|
23
28
|
end
|
24
29
|
|
25
30
|
end
|
@@ -1,34 +1,30 @@
|
|
1
|
-
require
|
1
|
+
require "coremidi"
|
2
2
|
|
3
3
|
module UniMIDI
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
# Load underlying devices using the coremidi gem
|
8
|
+
module CoreMIDI
|
9
|
+
|
10
|
+
module Loader
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# @return [Array<CoreMIDI::Source>]
|
15
|
+
def inputs
|
16
|
+
::CoreMIDI::Endpoint.all_by_type[:source]
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<CoreMIDI::Destination>]
|
20
|
+
def outputs
|
21
|
+
::CoreMIDI::Endpoint.all_by_type[:destination]
|
22
|
+
end
|
11
23
|
|
12
|
-
class Output < CongruousApiOutput
|
13
|
-
defer_to CoreMIDI::Destination
|
14
|
-
device_class CoreMIDI::Endpoint
|
15
|
-
end
|
16
|
-
|
17
|
-
class Device < CongruousApiDevice
|
18
|
-
defer_to CoreMIDI::Endpoint
|
19
|
-
input_class Input
|
20
|
-
output_class Output
|
21
|
-
|
22
|
-
def self.populate
|
23
|
-
klass = @deference[self].respond_to?(:all_by_type) ? @deference[self] : @device_class
|
24
|
-
@devices = {
|
25
|
-
:input => klass.all_by_type[:source].map { |d| @input_class.new(d) },
|
26
|
-
:output => klass.all_by_type[:destination].map { |d| @output_class.new(d) }
|
27
|
-
}
|
28
24
|
end
|
29
|
-
|
25
|
+
|
30
26
|
end
|
31
|
-
|
27
|
+
|
32
28
|
end
|
33
29
|
|
34
30
|
end
|
@@ -1,23 +1,28 @@
|
|
1
|
-
require
|
1
|
+
require "midi-jruby"
|
2
2
|
|
3
3
|
module UniMIDI
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
# Load underlying devices using the midi-jruby gem
|
8
|
+
module MIDIJRuby
|
9
|
+
|
10
|
+
module Loader
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# @return [Array<MIDIJRuby::Input>]
|
15
|
+
def inputs
|
16
|
+
::MIDIJRuby::Device.all_by_type[:input]
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<MIDIJRuby::Output>]
|
20
|
+
def outputs
|
21
|
+
::MIDIJRuby::Device.all_by_type[:output]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
11
25
|
|
12
|
-
class Output < CongruousApiOutput
|
13
|
-
defer_to MIDIJRuby::Output
|
14
|
-
device_class MIDIJRuby::Device
|
15
|
-
end
|
16
|
-
|
17
|
-
class Device < CongruousApiDevice
|
18
|
-
defer_to MIDIJRuby::Device
|
19
|
-
input_class Input
|
20
|
-
output_class Output
|
21
26
|
end
|
22
27
|
|
23
28
|
end
|
@@ -1,23 +1,28 @@
|
|
1
|
-
require
|
1
|
+
require "midi-winmm"
|
2
2
|
|
3
3
|
module UniMIDI
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
# Load underlying devices using the midi-winmm gem
|
8
|
+
module MIDIWinMM
|
9
|
+
|
10
|
+
module Loader
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# @return [Array<MIDIWinMM::Input>]
|
15
|
+
def inputs
|
16
|
+
::MIDIWinMM::Device.all_by_type[:input]
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Array<MIDIWinMM::Output>]
|
20
|
+
def outputs
|
21
|
+
::MIDIWinMM::Device.all_by_type[:output]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
11
25
|
|
12
|
-
class Output < CongruousApiOutput
|
13
|
-
defer_to MIDIWinMM::Output
|
14
|
-
device_class MIDIWinMM::Device
|
15
|
-
end
|
16
|
-
|
17
|
-
class Device < CongruousApiDevice
|
18
|
-
defer_to MIDIWinMM::Device
|
19
|
-
input_class Input
|
20
|
-
output_class Output
|
21
26
|
end
|
22
27
|
|
23
28
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module UniMIDI
|
2
|
+
|
3
|
+
# Module for command-line use of UniMIDI. Used by the bin/unimidi script
|
4
|
+
module Command
|
5
|
+
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# Execute a command
|
9
|
+
# @param [Symbol] command
|
10
|
+
# @param [Hash] options
|
11
|
+
# @return [Boolean]
|
12
|
+
def exec(command, options = {})
|
13
|
+
if [:l, :list, :list_devices].include?(command)
|
14
|
+
puts "input:"
|
15
|
+
Input.list
|
16
|
+
puts "output:"
|
17
|
+
Output.list
|
18
|
+
true
|
19
|
+
else
|
20
|
+
raise "Command #{command.to_s} not found"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module UniMIDI
|
2
|
+
|
3
|
+
# Common logic that is shared by both Input and Output devices
|
4
|
+
module Device
|
5
|
+
|
6
|
+
# Methods that are shared by both Input and Output classes
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
# Iterate over all devices of this direction (eg Input, Output)
|
12
|
+
def each(&block)
|
13
|
+
all.each { |device| yield(device) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Prints ids and names of each device to the console
|
17
|
+
# @return [Array<String>]
|
18
|
+
def list
|
19
|
+
all.map do |device|
|
20
|
+
name = device.pretty_name
|
21
|
+
puts(name)
|
22
|
+
name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Shortcut to select a device by its name
|
27
|
+
# @param [String, Symbol] name
|
28
|
+
# @return [Input, Output]
|
29
|
+
def find_by_name(name)
|
30
|
+
all.find { |device| name.to_s == device.name }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Streamlined console prompt that asks the user to select a device
|
34
|
+
# When their input is received, the device is selected and enabled
|
35
|
+
def gets(&block)
|
36
|
+
device = nil
|
37
|
+
class_name = self.name.split("::").last.downcase
|
38
|
+
puts ""
|
39
|
+
puts "Select a MIDI #{class_name}..."
|
40
|
+
while device.nil?
|
41
|
+
list
|
42
|
+
print "> "
|
43
|
+
selection = $stdin.gets.chomp
|
44
|
+
if selection != ""
|
45
|
+
selection = Integer(selection) rescue nil
|
46
|
+
device = all.find { |d| d.id == selection }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
device.open(&block) unless device.enabled?
|
50
|
+
device
|
51
|
+
end
|
52
|
+
|
53
|
+
# Select the first device and enable it
|
54
|
+
# @return [Input, Output]
|
55
|
+
def first(&block)
|
56
|
+
use_device(all.first, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Select the last device and enable it
|
60
|
+
# @return [Input, Output]
|
61
|
+
def last(&block)
|
62
|
+
use_device(all.last, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Select the device at the given index and enable it
|
66
|
+
# @param [Fixnum] index
|
67
|
+
# @return [Input, Output]
|
68
|
+
def use(index, &block)
|
69
|
+
index = case index
|
70
|
+
when :first then 0
|
71
|
+
when :last then all.size - 1
|
72
|
+
else index
|
73
|
+
end
|
74
|
+
use_device(all[index], &block)
|
75
|
+
end
|
76
|
+
alias_method :open, :use
|
77
|
+
|
78
|
+
# Select the device at the given index
|
79
|
+
# @param [Fixnum] index
|
80
|
+
# @return [Input, Output]
|
81
|
+
def [](index)
|
82
|
+
all[index]
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Enable the given device
|
88
|
+
# @param [Input, Output] device
|
89
|
+
# @return [Input, Output]
|
90
|
+
def use_device(device, &block)
|
91
|
+
device.open(&block) unless device.enabled?
|
92
|
+
device
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
# Methods that are shared by both Input and Output instances
|
98
|
+
module InstanceMethods
|
99
|
+
|
100
|
+
# @param [AlsaRawMIDI::Input, AlsaRawMIDI::Output, CoreMIDI::Destination, CoreMIDI::Source, MIDIJRuby::Input, MIDIJRuby::Output, MIDIWinMM::Input, MIDIWinMM::Output] device
|
101
|
+
def initialize(device)
|
102
|
+
@device = device
|
103
|
+
@enabled = false
|
104
|
+
|
105
|
+
populate_from_device
|
106
|
+
end
|
107
|
+
|
108
|
+
# Is this device ready for io?
|
109
|
+
# @return [Boolean]
|
110
|
+
def enabled?
|
111
|
+
@enabled = true if @device.enabled # keep the adapter in sync
|
112
|
+
@enabled
|
113
|
+
end
|
114
|
+
|
115
|
+
# Enable the device for use
|
116
|
+
# Params are passed to the underlying device object
|
117
|
+
# Can be passed a block to which the device will be passed in as the yieldparam
|
118
|
+
# @param [*Object] args
|
119
|
+
# @return [Input, Output] self
|
120
|
+
def open(*args, &block)
|
121
|
+
@device.open(*args) unless enabled?
|
122
|
+
@enabled = true
|
123
|
+
if block_given?
|
124
|
+
begin
|
125
|
+
yield(self)
|
126
|
+
ensure
|
127
|
+
close
|
128
|
+
end
|
129
|
+
else
|
130
|
+
at_exit do
|
131
|
+
close
|
132
|
+
end
|
133
|
+
self
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# A human readable display name for this device
|
138
|
+
# @return [String]
|
139
|
+
def pretty_name
|
140
|
+
"#{id}) #{name}"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Close the device
|
144
|
+
# Params are passed to the underlying device object
|
145
|
+
# @param [*Object] args
|
146
|
+
# @return [Boolean]
|
147
|
+
def close(*args)
|
148
|
+
@device.close(*args)
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
# Add attributes for the device instance
|
153
|
+
# :direction, :id, :name
|
154
|
+
def self.included(base)
|
155
|
+
base.send(:attr_reader, :direction)
|
156
|
+
base.send(:attr_reader, :id)
|
157
|
+
base.send(:attr_reader, :name)
|
158
|
+
base.send(:alias_method, :type, :direction)
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
# Populate the direction attribute
|
164
|
+
def populate_direction
|
165
|
+
@direction = case @device.type
|
166
|
+
when :source, :input then :input
|
167
|
+
when :destination, :output then :output
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Populate attributes from the underlying device object
|
172
|
+
def populate_from_device
|
173
|
+
@id = @device.id
|
174
|
+
@name = @device.name
|
175
|
+
populate_direction
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|