midi-eye 0.2.2 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +2 -2
- data/README.md +83 -0
- data/lib/midi-eye/listener.rb +104 -67
- data/lib/midi-eye/source.rb +44 -0
- data/lib/midi-eye.rb +9 -7
- data/test/{test_listener.rb → listener_test.rb} +3 -5
- metadata +36 -28
- data/README.rdoc +0 -73
- data/lib/midi-eye/unimidi_input.rb +0 -44
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2944fec81520048f22479d8fa72484928e3dcf65
|
4
|
+
data.tar.gz: bcab4013133af07447f36d6731e8840e9023b0d2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4b91db15538087d57aa6ab1d7fd250f69ff5f09d12ebfd5c7200813fc6e6db38815d45563cc5d5c5b50ddf7a22ce3b6b17990b398c255f19b53eaa9fce270ccb
|
7
|
+
data.tar.gz: 1c4f0fa96f717e7f179ad4fbdf9608d8ccb76e17d30d08f96d4a75590a7e2f409ff8d29598424bcc853dd17983f570c67aecc979d248f763c89190f38b9bb994
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright 2011 Ari Russo
|
1
|
+
Copyright 2011-2014 Ari Russo
|
2
2
|
|
3
3
|
Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
you may not use this file except in compliance with the License.
|
@@ -10,4 +10,4 @@ Unless required by applicable law or agreed to in writing, software
|
|
10
10
|
distributed under the License is distributed on an "AS IS" BASIS,
|
11
11
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
See the License for the specific language governing permissions and
|
13
|
-
limitations under the License.
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# MIDI EYE
|
2
|
+
|
3
|
+
MIDI input event listener for Ruby
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
`gem install midi-eye`
|
8
|
+
|
9
|
+
or using Bundler, add this to your Gemfile
|
10
|
+
|
11
|
+
`gem "midi-eye"`
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'midi-eye'
|
17
|
+
```
|
18
|
+
|
19
|
+
The following is an example that takes any note messages received from a unimidi input, transposes them up one octave and then sends them to an output
|
20
|
+
|
21
|
+
First, pick some MIDI IO ports
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
@input = UniMIDI::Input.gets
|
25
|
+
@output = UniMIDI::Output.gets
|
26
|
+
```
|
27
|
+
|
28
|
+
Then create a listener for the input port
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
transpose = MIDIEye::Listener.new(@input)
|
32
|
+
```
|
33
|
+
|
34
|
+
You can bind an event to the listener using `Listener#listen_for`
|
35
|
+
|
36
|
+
The listener will try to positively match the parameters you pass in to the properties of the messages it receives.
|
37
|
+
|
38
|
+
In this example, we specify that the listener listens for note on/off messages, which are identifiable by their class.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
transpose.listen_for(:class => [MIDIMessage::NoteOn, MIDIMessage::NoteOff]) do |event|
|
42
|
+
|
43
|
+
# raise the note value by an octave
|
44
|
+
event[:message].note += 12
|
45
|
+
|
46
|
+
# send the altered note message to the output you chose earlier
|
47
|
+
@output.puts(event[:message])
|
48
|
+
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
There is also the option of leaving out the parameters altogether and including using conditional if/unless/case/etc statements in the callback.
|
53
|
+
|
54
|
+
You can bind as many events to a listener as you wish by repeatedly calling `Listener#listen_for`
|
55
|
+
|
56
|
+
Once all the events are bound, start the listener
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
transpose.run
|
60
|
+
```
|
61
|
+
|
62
|
+
A listener can also be run in a background thread by passing in `:background => true`.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
transpose.run(:background => true)
|
66
|
+
|
67
|
+
transpose.join # join the background thread later
|
68
|
+
```
|
69
|
+
|
70
|
+
## Documentation
|
71
|
+
|
72
|
+
* [examples](http://github.com/arirusso/midi-eye/tree/master/examples)
|
73
|
+
* [rdoc](http://rdoc.info/gems/midi-eye)
|
74
|
+
|
75
|
+
## Author
|
76
|
+
|
77
|
+
* [Ari Russo](http://github.com/arirusso) <ari.russo at gmail.com>
|
78
|
+
|
79
|
+
## License
|
80
|
+
|
81
|
+
Apache 2.0, See the file LICENSE
|
82
|
+
|
83
|
+
Copyright (c) 2011-2014 Ari Russo
|
data/lib/midi-eye/listener.rb
CHANGED
@@ -1,65 +1,69 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
1
|
module MIDIEye
|
3
2
|
|
4
3
|
class Listener
|
5
4
|
|
6
5
|
attr_reader :events
|
7
6
|
attr_accessor :sources
|
8
|
-
|
9
|
-
@input_types = []
|
10
|
-
|
11
|
-
class << self
|
12
|
-
# a registry of input types
|
13
|
-
attr_reader :input_types
|
14
|
-
end
|
15
7
|
|
16
|
-
|
8
|
+
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to add to the list of sources for this listener
|
9
|
+
def initialize(inputs)
|
17
10
|
@sources = []
|
18
11
|
@event_queue = []
|
19
12
|
@events = []
|
20
13
|
|
21
|
-
add_input(
|
14
|
+
add_input(inputs)
|
22
15
|
end
|
23
16
|
|
24
|
-
#
|
17
|
+
# Does this listener use the given input?
|
18
|
+
# @param [UniMIDI::Input] input
|
19
|
+
# @return [Boolean]
|
25
20
|
def uses_input?(input)
|
26
|
-
|
21
|
+
@sources.any? { |source| source.uses?(input) }
|
27
22
|
end
|
28
23
|
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
24
|
+
# Add a MIDI source
|
25
|
+
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to add to the list of sources for this listener
|
26
|
+
# @return [Array<MIDIEye::Source>] The updated list of sources for this listener
|
27
|
+
def add_input(inputs)
|
28
|
+
inputs = [inputs].flatten.compact
|
29
|
+
new_sources = inputs.map do |input|
|
30
|
+
Source.new(input) unless uses_input?(input)
|
31
|
+
end
|
32
|
+
@sources += new_sources.compact
|
33
|
+
@sources
|
37
34
|
end
|
35
|
+
alias_method :add_inputs, :add_input
|
38
36
|
|
39
|
-
#
|
40
|
-
#
|
37
|
+
# Remove a MIDI source
|
38
|
+
# @param [Array<UniMIDI::Input>, UniMIDI::Input] inputs Input(s) to remove from the list of sources for this listener
|
39
|
+
# @return [Array<MIDIEye::Source>] The updated list of sources for this listener
|
41
40
|
def remove_input(inputs)
|
42
|
-
|
43
|
-
|
41
|
+
inputs = [inputs].flatten.compact
|
42
|
+
inputs.each do |input|
|
44
43
|
@sources.delete_if { |source| source.uses?(input) }
|
45
44
|
end
|
45
|
+
@sources
|
46
46
|
end
|
47
|
-
|
47
|
+
alias_method :remove_inputs, :remove_input
|
48
|
+
|
49
|
+
# @param [Symbol] name
|
48
50
|
def delete_event(name)
|
49
|
-
@events.delete_if { |
|
51
|
+
@events.delete_if { |event| event[:listener_name] == name }
|
50
52
|
end
|
51
53
|
|
52
|
-
#
|
54
|
+
# Start listening for MIDI messages
|
55
|
+
# @params [Hash] options
|
56
|
+
# @option options [Boolean] :background Run in a background thread
|
57
|
+
# @return [MIDIEye::Listener] self
|
53
58
|
def run(options = {})
|
54
|
-
listen
|
55
|
-
unless options[:background]
|
56
|
-
@listener.join
|
57
|
-
end
|
59
|
+
listen
|
60
|
+
join unless !!options[:background]
|
58
61
|
self
|
59
62
|
end
|
60
63
|
alias_method :start, :run
|
61
64
|
|
62
|
-
#
|
65
|
+
# Stop listening for MIDI messages.
|
66
|
+
# @return [MIDIEye::Listener] self
|
63
67
|
def close
|
64
68
|
@listener.kill unless @listener.nil?
|
65
69
|
@events.clear
|
@@ -69,31 +73,45 @@ module MIDIEye
|
|
69
73
|
end
|
70
74
|
alias_method :stop, :close
|
71
75
|
|
72
|
-
#
|
76
|
+
# Join the listener if it's being run in the background.
|
77
|
+
# @return [MIDIEye::Listener] self
|
73
78
|
def join
|
74
|
-
|
79
|
+
begin
|
80
|
+
@listener.join
|
81
|
+
rescue SystemExit, Interrupt
|
82
|
+
@listener.kill
|
83
|
+
raise
|
84
|
+
end
|
75
85
|
self
|
76
86
|
end
|
77
87
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
88
|
+
# Add an event to listen for
|
89
|
+
# @param [Hash] options
|
90
|
+
# @return [MIDIEye::Listener] self
|
91
|
+
def listen_for(options = {}, &callback)
|
92
|
+
raise "Listener must have a block" if callback.nil?
|
81
93
|
name = options[:listener_name]
|
82
94
|
options.delete(:listener_name)
|
83
|
-
|
95
|
+
event = {
|
96
|
+
:conditions => options,
|
97
|
+
:proc => callback,
|
98
|
+
:listener_name => name
|
99
|
+
}
|
100
|
+
@events << event
|
84
101
|
self
|
85
102
|
end
|
86
103
|
alias_method :on_message, :listen_for
|
87
104
|
alias_method :listen, :listen_for
|
88
105
|
|
89
|
-
#
|
106
|
+
# Poll the input source for new input. This will normally be done by the background thread
|
90
107
|
def poll
|
91
108
|
@sources.each do |input|
|
92
109
|
input.poll do |objs|
|
93
110
|
objs.each do |batch|
|
94
|
-
[batch[:messages]].flatten.
|
95
|
-
|
96
|
-
|
111
|
+
messages = [batch[:messages]].flatten.compact
|
112
|
+
messages.each do |message|
|
113
|
+
unless message.nil?
|
114
|
+
data = { :message => message, :timestamp => batch[:timestamp] }
|
97
115
|
@events.each { |name| queue_event(name, data) }
|
98
116
|
end
|
99
117
|
end
|
@@ -103,48 +121,67 @@ module MIDIEye
|
|
103
121
|
end
|
104
122
|
|
105
123
|
private
|
106
|
-
|
107
|
-
#
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
trigger_queued_events unless @event_queue.empty?
|
115
|
-
sleep(t)
|
116
|
-
end
|
124
|
+
|
125
|
+
# A loop that runs while the listener is active
|
126
|
+
def listen_loop
|
127
|
+
interval = 1.0/1000
|
128
|
+
loop do
|
129
|
+
poll
|
130
|
+
trigger_queued_events unless @event_queue.empty?
|
131
|
+
sleep(interval)
|
117
132
|
end
|
118
133
|
end
|
119
134
|
|
120
|
-
#
|
135
|
+
# Start the background listener thread
|
136
|
+
def listen
|
137
|
+
@listener = Thread.new { listen_loop }
|
138
|
+
@listener.abort_on_exception = true
|
139
|
+
true
|
140
|
+
end
|
141
|
+
|
142
|
+
# Trigger all queued events
|
121
143
|
def trigger_queued_events
|
122
144
|
@event_queue.length.times { trigger_event(@event_queue.shift) }
|
123
145
|
end
|
124
146
|
|
125
|
-
#
|
147
|
+
# Does the given message meet the given conditions?
|
126
148
|
def meets_conditions?(conditions, message)
|
127
|
-
|
128
|
-
message.respond_to?(key)
|
129
|
-
|
149
|
+
results = conditions.map do |key, value|
|
150
|
+
if message.respond_to?(key)
|
151
|
+
if value.kind_of?(Array)
|
152
|
+
value.include?(message.send(key))
|
153
|
+
else
|
154
|
+
value.eql?(message.send(key))
|
155
|
+
end
|
156
|
+
else
|
157
|
+
false
|
158
|
+
end
|
159
|
+
end
|
160
|
+
results.all?
|
130
161
|
end
|
131
162
|
|
132
|
-
#
|
163
|
+
# Trigger an event
|
133
164
|
def trigger_event(event)
|
134
|
-
|
135
|
-
|
136
|
-
|
165
|
+
action = event[:action]
|
166
|
+
conditions = action[:conditions]
|
167
|
+
if conditions.nil? || meets_conditions?(conditions, event[:message][:message])
|
168
|
+
begin
|
137
169
|
action[:proc].call(event[:message])
|
170
|
+
rescue
|
171
|
+
# help
|
138
172
|
end
|
139
|
-
rescue
|
140
173
|
end
|
141
174
|
end
|
142
175
|
|
143
|
-
#
|
144
|
-
def queue_event(
|
145
|
-
|
176
|
+
# Add an event to the trigger queue
|
177
|
+
def queue_event(action, message)
|
178
|
+
event = {
|
179
|
+
:action => action,
|
180
|
+
:message => message
|
181
|
+
}
|
182
|
+
@event_queue << event
|
146
183
|
end
|
147
184
|
|
148
185
|
end
|
149
186
|
|
150
|
-
end
|
187
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module MIDIEye
|
2
|
+
|
3
|
+
# Retrieves new messages from a unimidi input buffer
|
4
|
+
class Source
|
5
|
+
|
6
|
+
attr_reader :device, :pointer
|
7
|
+
|
8
|
+
# @param [UniMIDI::Input] input
|
9
|
+
def initialize(input)
|
10
|
+
@parser = Nibbler.new
|
11
|
+
@pointer = 0
|
12
|
+
@device = input
|
13
|
+
end
|
14
|
+
|
15
|
+
# Grabs new messages from the input buffer
|
16
|
+
def poll(&block)
|
17
|
+
messages = @device.buffer.slice(@pointer, @device.buffer.length - @pointer)
|
18
|
+
@pointer = @device.buffer.length
|
19
|
+
messages.each do |raw_message|
|
20
|
+
unless raw_message.nil?
|
21
|
+
parsed_messages = @parser.parse(raw_message[:data], :timestamp => raw_message[:timestamp]) rescue nil
|
22
|
+
objects = [parsed_messages].flatten.compact
|
23
|
+
yield(objects)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Whether the given object is a UniMIDI input
|
29
|
+
# @param [Object] input
|
30
|
+
# @return [Boolean]
|
31
|
+
def self.compatible?(input)
|
32
|
+
input.respond_to?(:gets) && input.respond_to?(:buffer)
|
33
|
+
end
|
34
|
+
|
35
|
+
# If this source was created from the given input
|
36
|
+
# @param [UniMIDI::Input] input
|
37
|
+
# @return [Boolean]
|
38
|
+
def uses?(input)
|
39
|
+
@device == input
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/midi-eye.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
1
|
#
|
3
2
|
# midi-eye
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
3
|
+
#
|
4
|
+
# MIDI input event listener for Ruby
|
5
|
+
# (c)2011-2014 Ari Russo
|
6
|
+
# Licensed under the Apache 2.0 License
|
7
7
|
#
|
8
8
|
|
9
|
+
# libs
|
9
10
|
require 'midi-message'
|
10
11
|
require 'nibbler'
|
11
12
|
require 'unimidi'
|
12
13
|
|
14
|
+
# classes
|
13
15
|
require 'midi-eye/listener'
|
14
|
-
require 'midi-eye/
|
16
|
+
require 'midi-eye/source'
|
15
17
|
|
16
18
|
module MIDIEye
|
17
19
|
|
18
|
-
VERSION = "0.
|
20
|
+
VERSION = "0.3.1"
|
19
21
|
|
20
|
-
end
|
22
|
+
end
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'helper'
|
1
|
+
require "helper"
|
4
2
|
|
5
3
|
class ListenerTest < Test::Unit::TestCase
|
6
4
|
|
@@ -98,7 +96,7 @@ class ListenerTest < Test::Unit::TestCase
|
|
98
96
|
input = $test_device[:input]
|
99
97
|
output = $test_device[:output]
|
100
98
|
listener = Listener.new(input)
|
101
|
-
assert_equal(
|
99
|
+
assert_equal(Source, listener.sources.first.class)
|
102
100
|
close_all(input, output, listener)
|
103
101
|
end
|
104
102
|
|
@@ -153,4 +151,4 @@ class ListenerTest < Test::Unit::TestCase
|
|
153
151
|
listener.join
|
154
152
|
end
|
155
153
|
|
156
|
-
end
|
154
|
+
end
|
metadata
CHANGED
@@ -1,85 +1,93 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: midi-eye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ari Russo
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-08-30 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: midi-message
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: midi-nibbler
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - "~>"
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
42
|
name: unimidi
|
38
|
-
requirement:
|
39
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - "~>"
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
48
|
type: :runtime
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
47
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A utility for dealing with MIDI input in Ruby.
|
48
56
|
email:
|
49
57
|
- ari.russo@gmail.com
|
50
58
|
executables: []
|
51
59
|
extensions: []
|
52
60
|
extra_rdoc_files: []
|
53
61
|
files:
|
54
|
-
-
|
55
|
-
-
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
56
64
|
- lib/midi-eye.rb
|
65
|
+
- lib/midi-eye/listener.rb
|
66
|
+
- lib/midi-eye/source.rb
|
57
67
|
- test/helper.rb
|
58
|
-
- test/
|
59
|
-
- LICENSE
|
60
|
-
- README.rdoc
|
68
|
+
- test/listener_test.rb
|
61
69
|
homepage: http://github.com/arirusso/midi-eye
|
62
|
-
licenses:
|
70
|
+
licenses:
|
71
|
+
- Apache 2.0
|
72
|
+
metadata: {}
|
63
73
|
post_install_message:
|
64
74
|
rdoc_options: []
|
65
75
|
require_paths:
|
66
76
|
- lib
|
67
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
78
|
requirements:
|
70
|
-
- -
|
79
|
+
- - ">="
|
71
80
|
- !ruby/object:Gem::Version
|
72
81
|
version: '0'
|
73
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
83
|
requirements:
|
76
|
-
- -
|
84
|
+
- - ">="
|
77
85
|
- !ruby/object:Gem::Version
|
78
86
|
version: 1.3.6
|
79
87
|
requirements: []
|
80
88
|
rubyforge_project: midi-eye
|
81
|
-
rubygems_version:
|
89
|
+
rubygems_version: 2.2.2
|
82
90
|
signing_key:
|
83
|
-
specification_version:
|
91
|
+
specification_version: 4
|
84
92
|
summary: MIDI event listener for Ruby
|
85
93
|
test_files: []
|
data/README.rdoc
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
= midi-eye
|
2
|
-
|
3
|
-
A transparent MIDI input event listener for Ruby
|
4
|
-
|
5
|
-
== Requirements
|
6
|
-
|
7
|
-
* {midi-message}[http://github.com/arirusso/midi-message]
|
8
|
-
* {nibbler}[http://github.com/arirusso/nibbler]
|
9
|
-
* {unimidi}[http://github.com/arirusso/unimidi]
|
10
|
-
|
11
|
-
== Install
|
12
|
-
|
13
|
-
gem install midi-eye
|
14
|
-
|
15
|
-
== Usage
|
16
|
-
|
17
|
-
require 'midi-eye'
|
18
|
-
|
19
|
-
The following is an example that takes any note messages received from a unimidi input, transposes them up one octave and then sends them to an output
|
20
|
-
|
21
|
-
First, initialize the MIDI IO ports
|
22
|
-
|
23
|
-
@input = UniMIDI::Input.gets
|
24
|
-
@output = UniMIDI::Output.gets
|
25
|
-
|
26
|
-
Then create a listener for the input port
|
27
|
-
|
28
|
-
transpose = MIDIEye::Listener.new(@input)
|
29
|
-
|
30
|
-
You can bind an event to the listener using Listener#listen_for
|
31
|
-
|
32
|
-
The listener will try to positively match the parameters you pass in to the properties of the messages it receives.
|
33
|
-
|
34
|
-
In this example, we will tell the listener to listen for note on/off messages which are easily identifiable by their class
|
35
|
-
|
36
|
-
You also have the option of leaving out the parameters altogether and including using conditional if/unless/case/etc statements in your callback
|
37
|
-
|
38
|
-
transpose.listen_for(:class => [MIDIMessage::NoteOn, MIDIMessage::NoteOff]) do |event|
|
39
|
-
|
40
|
-
# raise the note value by an octave
|
41
|
-
event[:message].note += 12
|
42
|
-
|
43
|
-
# send the altered note message to the output you chose earlier
|
44
|
-
@output.puts(event[:message])
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
You can bind as many events to a listener as you wish, just keep calling Listener#listen_for
|
49
|
-
|
50
|
-
Once all the events are bound, start the listener
|
51
|
-
|
52
|
-
transpose.run
|
53
|
-
|
54
|
-
A listener can also be run in a background thread by passing in :background => true.
|
55
|
-
|
56
|
-
transpose.run(:background => true)
|
57
|
-
|
58
|
-
transpose.join # join the background thread later
|
59
|
-
|
60
|
-
== Documentation
|
61
|
-
|
62
|
-
* {examples}[http://github.com/arirusso/midi-eye/tree/master/examples]
|
63
|
-
* {rdoc}[http://rdoc.info/gems/midi-eye]
|
64
|
-
|
65
|
-
== Author
|
66
|
-
|
67
|
-
* {Ari Russo}[http://github.com/arirusso] <ari.russo at gmail.com>
|
68
|
-
|
69
|
-
== License
|
70
|
-
|
71
|
-
Apache 2.0, See the file LICENSE
|
72
|
-
|
73
|
-
Copyright (c) 2011 Ari Russo
|
@@ -1,44 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
module MIDIEye
|
4
|
-
|
5
|
-
# this class deals with retrieving new messages from
|
6
|
-
# a unimidi input buffer
|
7
|
-
class UniMIDIInput
|
8
|
-
|
9
|
-
attr_reader :device, :pointer
|
10
|
-
|
11
|
-
def initialize(input)
|
12
|
-
@parser = Nibbler.new
|
13
|
-
@pointer = 0
|
14
|
-
@device = input
|
15
|
-
end
|
16
|
-
|
17
|
-
# this grabs new messages from the unimidi buffer
|
18
|
-
def poll(&block)
|
19
|
-
msgs = @device.buffer.slice(@pointer, @device.buffer.length - @pointer)
|
20
|
-
@pointer = @device.buffer.length
|
21
|
-
msgs.each do |raw_msg|
|
22
|
-
unless raw_msg.nil?
|
23
|
-
objs = [@parser.parse(raw_msg[:data], :timestamp => raw_msg[:timestamp])].flatten.compact rescue []
|
24
|
-
yield(objs)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# if <em>input</em> looks like a unimidi input, this returns true
|
30
|
-
def self.is_compatible?(input)
|
31
|
-
input.respond_to?(:gets) && input.respond_to?(:buffer)
|
32
|
-
end
|
33
|
-
|
34
|
-
# if this source was created from <em>input</em>
|
35
|
-
def uses?(input)
|
36
|
-
@device == input
|
37
|
-
end
|
38
|
-
|
39
|
-
# add this class to the Listener class' known input types
|
40
|
-
Listener.input_types << self
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|