midi-eye 0.3.6 → 0.3.7
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 +4 -4
- data/lib/midi-eye.rb +6 -6
- data/lib/midi-eye/listener.rb +24 -24
- data/test/helper.rb +13 -10
- data/test/listener_test.rb +175 -138
- 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: 7e90eda3aee9f3edfbeb121e91a8de5332499ae1
|
4
|
+
data.tar.gz: 50cc2dc4499ca9f22c61183c0583ba4b98b9694d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91a4e30f101d2762dabb0d220fd4ca9d12591fbd7821ffe023c86e3aedba9810e2729625b8979aa129fa54943a374485d5e48ca3cfdd8b1f6e0a1581ddaa9dd1
|
7
|
+
data.tar.gz: b08bb9377641d90d296334000a76dfda3a5f70b2c45c33dec5c263a769ce332c2c251cac5fe26b02f7e6016205cb0053dc4cfbf687c2061e64c520d96fd88d99
|
data/lib/midi-eye.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
# midi-eye
|
3
3
|
#
|
4
4
|
# MIDI input event listener for Ruby
|
5
|
-
# (c)2011-2014 Ari Russo
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# (c)2011-2014 Ari Russo
|
6
|
+
# Apache 2.0 License
|
7
|
+
#
|
8
8
|
|
9
9
|
# libs
|
10
10
|
require "midi-message"
|
@@ -17,7 +17,7 @@ require "midi-eye/listener"
|
|
17
17
|
require "midi-eye/source"
|
18
18
|
|
19
19
|
module MIDIEye
|
20
|
-
|
21
|
-
VERSION = "0.3.
|
22
|
-
|
20
|
+
|
21
|
+
VERSION = "0.3.7"
|
22
|
+
|
23
23
|
end
|
data/lib/midi-eye/listener.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
module MIDIEye
|
2
|
-
|
2
|
+
|
3
3
|
class Listener
|
4
|
-
|
5
|
-
attr_reader :event
|
4
|
+
|
5
|
+
attr_reader :event
|
6
6
|
attr_accessor :sources
|
7
|
-
|
7
|
+
|
8
8
|
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to add to the list of sources for this listener
|
9
9
|
def initialize(inputs)
|
10
10
|
@sources = []
|
11
11
|
@event = Event.new
|
12
|
-
|
12
|
+
|
13
13
|
add_input(inputs)
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
# Does this listener use the given input?
|
17
17
|
# @param [UniMIDI::Input] input
|
18
18
|
# @return [Boolean]
|
19
19
|
def uses_input?(input)
|
20
20
|
@sources.any? { |source| source.uses?(input) }
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# Add a MIDI source
|
24
24
|
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to add to the list of sources for this listener
|
25
25
|
# @return [Array<MIDIEye::Source>] The updated list of sources for this listener
|
@@ -32,7 +32,7 @@ module MIDIEye
|
|
32
32
|
@sources
|
33
33
|
end
|
34
34
|
alias_method :add_inputs, :add_input
|
35
|
-
|
35
|
+
|
36
36
|
# Remove a MIDI source
|
37
37
|
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to remove from the list of sources for this listener
|
38
38
|
# @return [Array<MIDIEye::Source>] The updated list of sources for this listener
|
@@ -44,18 +44,18 @@ module MIDIEye
|
|
44
44
|
@sources
|
45
45
|
end
|
46
46
|
alias_method :remove_inputs, :remove_input
|
47
|
-
|
47
|
+
|
48
48
|
# Start listening for MIDI messages
|
49
49
|
# @params [Hash] options
|
50
50
|
# @option options [Boolean] :background Run in a background thread
|
51
51
|
# @return [MIDIEye::Listener] self
|
52
|
-
def run(options = {})
|
52
|
+
def run(options = {})
|
53
53
|
listen
|
54
54
|
join unless !!options[:background]
|
55
55
|
self
|
56
56
|
end
|
57
57
|
alias_method :start, :run
|
58
|
-
|
58
|
+
|
59
59
|
# Stop listening for MIDI messages.
|
60
60
|
# @return [MIDIEye::Listener] self
|
61
61
|
def close
|
@@ -69,9 +69,9 @@ module MIDIEye
|
|
69
69
|
# Is the listener running?
|
70
70
|
# @return [Boolean]
|
71
71
|
def running?
|
72
|
-
!@listener.nil?
|
72
|
+
!@listener.nil? && @listener.alive?
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
# Join the listener if it's being run in the background.
|
76
76
|
# @return [MIDIEye::Listener] self
|
77
77
|
def join
|
@@ -89,20 +89,20 @@ module MIDIEye
|
|
89
89
|
# @return [Boolean]
|
90
90
|
def delete_event(event_name)
|
91
91
|
!@event.delete(event_name).nil?
|
92
|
-
end
|
93
|
-
|
92
|
+
end
|
93
|
+
|
94
94
|
# Add an event to listen for
|
95
95
|
# @param [Hash] options
|
96
96
|
# @return [MIDIEye::Listener] self
|
97
97
|
def listen_for(options = {}, &callback)
|
98
98
|
raise "Listener must have a block" if callback.nil?
|
99
99
|
@event.add(options, &callback)
|
100
|
-
self
|
100
|
+
self
|
101
101
|
end
|
102
102
|
alias_method :on_message, :listen_for
|
103
103
|
alias_method :listen, :listen_for
|
104
|
-
|
105
|
-
# Poll the input source for new input. This will normally be done by the background thread
|
104
|
+
|
105
|
+
# Poll the input source for new input. This will normally be done by the background thread
|
106
106
|
def poll
|
107
107
|
@sources.each do |input|
|
108
108
|
input.poll do |objs|
|
@@ -113,7 +113,7 @@ module MIDIEye
|
|
113
113
|
data = { :message => message, :timestamp => batch[:timestamp] }
|
114
114
|
@event.enqueue_all(data)
|
115
115
|
end
|
116
|
-
end
|
116
|
+
end
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
@@ -130,8 +130,8 @@ module MIDIEye
|
|
130
130
|
sleep(interval)
|
131
131
|
end
|
132
132
|
end
|
133
|
-
|
134
|
-
# Start the background listener thread
|
133
|
+
|
134
|
+
# Start the background listener thread
|
135
135
|
def listen
|
136
136
|
@listener = Thread.new do
|
137
137
|
begin
|
@@ -143,7 +143,7 @@ module MIDIEye
|
|
143
143
|
@listener.abort_on_exception = true
|
144
144
|
true
|
145
145
|
end
|
146
|
-
|
147
|
-
end
|
148
|
-
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
149
|
end
|
data/test/helper.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
1
|
dir = File.dirname(File.expand_path(__FILE__))
|
4
|
-
$LOAD_PATH.unshift
|
2
|
+
$LOAD_PATH.unshift(dir + "/../lib")
|
3
|
+
|
4
|
+
require "test/unit"
|
5
|
+
require "mocha/test_unit"
|
6
|
+
require "shoulda-context"
|
5
7
|
|
6
|
-
require
|
7
|
-
require 'midi-eye'
|
8
|
+
require "midi-eye"
|
8
9
|
|
9
10
|
module TestHelper
|
10
|
-
|
11
|
-
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def select_devices
|
12
15
|
$test_device ||= {}
|
13
16
|
{ :input => UniMIDI::Input, :output => UniMIDI::Output }.each do |type, klass|
|
14
17
|
$test_device[type] = klass.gets
|
15
18
|
end
|
16
19
|
end
|
17
|
-
|
20
|
+
|
18
21
|
def close_all(input, output, listener)
|
19
22
|
listener.close
|
20
23
|
input.clear_buffer
|
@@ -22,7 +25,7 @@ module TestHelper
|
|
22
25
|
output.close
|
23
26
|
sleep(0.1)
|
24
27
|
end
|
25
|
-
|
28
|
+
|
26
29
|
end
|
27
30
|
|
28
|
-
TestHelper.select_devices
|
31
|
+
TestHelper.select_devices
|
data/test/listener_test.rb
CHANGED
@@ -2,153 +2,190 @@ require "helper"
|
|
2
2
|
|
3
3
|
class ListenerTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
context "Listener" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
sleep(0.2)
|
9
|
+
@output = $test_device[:output]
|
10
|
+
@input = $test_device[:input]
|
11
|
+
@listener = MIDIEye::Listener.new(@input)
|
12
|
+
end
|
13
|
+
|
14
|
+
context "basic" do
|
15
|
+
|
16
|
+
setup do
|
17
|
+
@i = 0
|
18
|
+
@listener.listen_for do |event|
|
19
|
+
@i += 1
|
20
|
+
assert_equal(1, @i)
|
21
|
+
TestHelper.close_all(@input, @output, @listener)
|
22
|
+
end
|
23
|
+
@listener.start(:background => true)
|
24
|
+
sleep(0.5)
|
20
25
|
end
|
26
|
+
|
27
|
+
should "receive messages" do
|
28
|
+
@output.puts(0x90, 0x40, 0x10)
|
29
|
+
@listener.join
|
30
|
+
end
|
31
|
+
|
21
32
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
33
|
+
|
34
|
+
context "rapid control change" do
|
35
|
+
|
36
|
+
setup do
|
37
|
+
@i = 0
|
38
|
+
@listener.listen_for(:class => MIDIMessage::ControlChange) do |event|
|
39
|
+
@i += 1
|
40
|
+
if @i == 5 * 126
|
41
|
+
TestHelper.close_all(@input, @output, @listener)
|
42
|
+
assert_equal(5 * 126, @i)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@listener.start(:background => true)
|
46
|
+
sleep(0.5)
|
27
47
|
end
|
48
|
+
|
49
|
+
should "receive messages" do
|
50
|
+
5.times do
|
51
|
+
126.times do |i|
|
52
|
+
@output.puts(176, 1, i+1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@listener.join
|
56
|
+
end
|
57
|
+
|
28
58
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
59
|
+
|
60
|
+
context "control change" do
|
61
|
+
|
62
|
+
setup do
|
63
|
+
@listener.listen_for(:class => MIDIMessage::ControlChange) do |event|
|
64
|
+
assert_equal(MIDIMessage::ControlChange, event[:message].class)
|
65
|
+
assert_equal(1, event[:message].index)
|
66
|
+
assert_equal(35, event[:message].value)
|
67
|
+
assert_equal([176, 1, 35], event[:message].to_bytes)
|
68
|
+
TestHelper.close_all(@input, @output, @listener)
|
69
|
+
end
|
70
|
+
@listener.start(:background => true)
|
71
|
+
sleep(0.5)
|
72
|
+
end
|
73
|
+
|
74
|
+
should "receive messages" do
|
75
|
+
@output.puts(176, 1, 35)
|
76
|
+
@listener.join
|
77
|
+
end
|
43
78
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
79
|
+
|
80
|
+
context "sysex" do
|
81
|
+
|
82
|
+
setup do
|
83
|
+
@listener.listen_for(:class => MIDIMessage::SystemExclusive::Command) do |event|
|
84
|
+
assert_equal(MIDIMessage::SystemExclusive::Command, event[:message].class)
|
85
|
+
assert_equal([0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7], event[:message].to_byte_array)
|
86
|
+
TestHelper.close_all(@input, @output, @listener)
|
87
|
+
end
|
88
|
+
@listener.start(:background => true)
|
89
|
+
sleep(0.5)
|
90
|
+
end
|
91
|
+
|
92
|
+
should "receive messages" do
|
93
|
+
@output.puts(0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7)
|
94
|
+
@listener.join
|
95
|
+
end
|
96
|
+
|
60
97
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
assert_equal(1, listener.sources.size)
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_remove_input
|
85
|
-
sleep(0.2)
|
86
|
-
output = $test_device[:output]
|
87
|
-
input = $test_device[:input]
|
88
|
-
listener = Listener.new(input)
|
89
|
-
assert_equal(1, listener.sources.size)
|
90
|
-
listener.remove_input(input)
|
91
|
-
assert_equal(0, listener.sources.size)
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_recognize_input_class
|
95
|
-
sleep(0.2)
|
96
|
-
input = $test_device[:input]
|
97
|
-
output = $test_device[:output]
|
98
|
-
listener = Listener.new(input)
|
99
|
-
assert_equal(Source, listener.sources.first.class)
|
100
|
-
close_all(input, output, listener)
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_listen_for_basic
|
104
|
-
sleep(0.2)
|
105
|
-
@i = 0
|
106
|
-
output = $test_device[:output]
|
107
|
-
input = $test_device[:input]
|
108
|
-
listener = Listener.new(input)
|
109
|
-
listener.listen_for do |event|
|
110
|
-
@i += 1
|
111
|
-
assert_equal(1, @i)
|
112
|
-
close_all(input, output, listener)
|
98
|
+
|
99
|
+
context "note on" do
|
100
|
+
|
101
|
+
setup do
|
102
|
+
@listener.listen_for(:class => MIDIMessage::NoteOff) do |event|
|
103
|
+
assert_equal(MIDIMessage::NoteOff, event[:message].class)
|
104
|
+
assert_equal(0x50, event[:message].note)
|
105
|
+
assert_equal(0x40, event[:message].velocity)
|
106
|
+
assert_equal([0x80, 0x50, 0x40], event[:message].to_bytes)
|
107
|
+
TestHelper.close_all(@input, @output, @listener)
|
108
|
+
end
|
109
|
+
@listener.start(:background => true)
|
110
|
+
sleep(0.5)
|
111
|
+
end
|
112
|
+
|
113
|
+
should "receive messages" do
|
114
|
+
@output.puts(0x80, 0x50, 0x40)
|
115
|
+
@listener.join
|
116
|
+
end
|
117
|
+
|
113
118
|
end
|
114
|
-
listener.start(:background => true)
|
115
|
-
sleep(0.5)
|
116
|
-
output.puts(0x90, 0x40, 0x10)
|
117
|
-
listener.join
|
118
|
-
end
|
119
119
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
120
|
+
context "#delete_event" do
|
121
|
+
|
122
|
+
setup do
|
123
|
+
@listener.listen_for(:listener_name => :test) do |event|
|
124
|
+
assert_equal(1, @listener.event.count)
|
125
|
+
@listener.delete_event(:test)
|
126
|
+
assert_equal(0, @listener.event.count)
|
127
|
+
TestHelper.close_all(@input, @output, @listener)
|
128
|
+
end
|
129
|
+
@listener.start(:background => true)
|
130
|
+
sleep(0.5)
|
131
|
+
end
|
132
|
+
|
133
|
+
should "receive messages" do
|
134
|
+
@output.puts(0x90, 0x70, 0x20)
|
135
|
+
@listener.join
|
136
|
+
end
|
137
|
+
|
129
138
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
sleep(0.2)
|
138
|
-
output = $test_device[:output]
|
139
|
-
input = $test_device[:input]
|
140
|
-
listener = Listener.new(input)
|
141
|
-
listener.listen_for(:class => NoteOff) do |event|
|
142
|
-
assert_equal(NoteOff, event[:message].class)
|
143
|
-
assert_equal(0x50, event[:message].note)
|
144
|
-
assert_equal(0x40, event[:message].velocity)
|
145
|
-
assert_equal([0x80, 0x50, 0x40], event[:message].to_bytes)
|
146
|
-
close_all(input, output, listener)
|
139
|
+
|
140
|
+
context "#uses_input?" do
|
141
|
+
|
142
|
+
should "acknowledge input" do
|
143
|
+
assert @listener.uses_input?(@input)
|
144
|
+
end
|
145
|
+
|
147
146
|
end
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
147
|
+
|
148
|
+
context "#add_input" do
|
149
|
+
|
150
|
+
should "ignore redundant input" do
|
151
|
+
num_sources = @listener.sources.size
|
152
|
+
@listener.add_input(@input)
|
153
|
+
assert_equal num_sources, @listener.sources.size
|
154
|
+
assert_equal MIDIEye::Source, @listener.sources.last.class
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
context "#remove_input" do
|
160
|
+
|
161
|
+
should "remove input" do
|
162
|
+
num_sources = @listener.sources.size
|
163
|
+
assert num_sources > 0
|
164
|
+
@listener.remove_input(@input)
|
165
|
+
assert_equal num_sources - 1, @listener.sources.size
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
context "#close" do
|
171
|
+
|
172
|
+
setup do
|
173
|
+
@listener.listen_for(:class => MIDIMessage::NoteOff) do |event|
|
174
|
+
TestHelper.close_all(@input, @output, @listener)
|
175
|
+
end
|
176
|
+
@listener.start(:background => true)
|
177
|
+
sleep(0.5)
|
178
|
+
@output.puts(0x80, 0x50, 0x40)
|
179
|
+
@listener.join
|
180
|
+
end
|
181
|
+
|
182
|
+
should "close" do
|
183
|
+
assert @listener.close
|
184
|
+
refute @listener.running?
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
152
189
|
end
|
153
|
-
|
190
|
+
|
154
191
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: midi-eye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ari Russo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: midi-message
|