midi-eye 0.2.2 → 0.3.1
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 +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
|