micromidi 0.0.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.
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ module MicroMIDI
4
+
5
+ class State
6
+
7
+ Default = {
8
+ :channel => 0,
9
+ :octave => 2,
10
+ :velocity => 100
11
+ }
12
+
13
+ attr_accessor :auto_output,
14
+ :channel,
15
+ :last_note,
16
+ :octave,
17
+ :sysex_node,
18
+ :super_sticky,
19
+ :velocity
20
+
21
+ attr_reader :inputs,
22
+ :last_command,
23
+ :listeners,
24
+ :outputs,
25
+ :output_cache,
26
+ :start_time,
27
+ :thru_listeners
28
+
29
+ def initialize(ins, outs, options = {})
30
+ @auto_output = true
31
+ @last_command = nil
32
+ @last_note = nil
33
+ @listeners = []
34
+ @thru_listeners = []
35
+ @output_cache = []
36
+ @start_time = Time.now.to_f
37
+ @super_sticky = false
38
+
39
+ @channel = options[:channel] || Default[:channel]
40
+ @velocity = options[:velocity] || Default[:velocity]
41
+ @octave = options[:octave] || Default[:octave]
42
+
43
+ @inputs = ins
44
+ @outputs = outs
45
+ end
46
+
47
+ def record(m, a, b, outp)
48
+ ts = now
49
+ @output_cache << { :message => outp, :timestamp => ts }
50
+ @last_command = { :method => m, :args => a, :block => b, :timestamp => ts }
51
+ end
52
+
53
+ def toggle_super_sticky
54
+ @super_sticky = !@super_sticky
55
+ end
56
+
57
+ def toggle_auto_output
58
+ @auto_output = !@auto_output
59
+ end
60
+
61
+ def message_properties(opts, *props)
62
+ output = {}
63
+ props.each do |prop|
64
+ output[prop] = opts[prop]
65
+ self.send("#{prop.to_s}=", output[prop]) if !output[prop].nil? && (self.send(prop).nil? || @super_sticky)
66
+ output[prop] ||= self.send(prop.to_s)
67
+ end
68
+ output
69
+ end
70
+
71
+ private
72
+
73
+ def now
74
+ ((Time.now.to_f - @start_time) * 1000)
75
+ end
76
+
77
+ end
78
+
79
+ end
data/lib/micromidi.rb ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # micromidi
4
+ # A Ruby DSL for MIDI
5
+ #
6
+ # (c)2011 Ari Russo
7
+ # licensed under the Apache 2.0 License
8
+ #
9
+
10
+ # libs
11
+ require 'midi-eye'
12
+ require 'midi-message'
13
+ require 'unimidi'
14
+
15
+ module MicroMIDI
16
+
17
+ VERSION = "0.0.7"
18
+
19
+ module Instructions
20
+ end
21
+
22
+ def self.new(*a, &block)
23
+ message(*a, &block)
24
+ end
25
+
26
+ def self.message(*args, &block)
27
+ ins, outs = *process_devices(args)
28
+ MicroMIDI::Context.new(ins, outs, &block)
29
+ end
30
+ class << self
31
+ alias_method :using, :message
32
+ end
33
+
34
+ module IO
35
+
36
+ def self.new(*args)
37
+ MicroMIDI.message(*args)
38
+ end
39
+
40
+ end
41
+
42
+ private
43
+
44
+ def self.process_devices(args)
45
+ ins = args.find_all { |d| d.respond_to?(:type) && d.type == :input && d.respond_to?(:gets) }
46
+ outs = args.find_all { |d| d.respond_to?(:puts) }
47
+ [ins, outs]
48
+ end
49
+
50
+ end
51
+ MIDI = MicroMIDI
52
+
53
+ # modules
54
+ require 'micromidi/instructions/composite'
55
+
56
+ # classes
57
+ require 'micromidi/context'
58
+ require 'micromidi/state'
59
+ require 'micromidi/instructions/process'
60
+ require 'micromidi/instructions/input'
61
+ require 'micromidi/instructions/message'
62
+ require 'micromidi/instructions/output'
63
+ require 'micromidi/instructions/sticky'
64
+ require 'micromidi/instructions/sysex'
65
+
66
+ # re-open
67
+ require 'micromidi/instructions/shorthand'
data/lib/midi.rb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # micromidi
4
+ # A Ruby DSL for MIDI
5
+ #
6
+ # (c)2011 Ari Russo
7
+ # licensed under the Apache 2.0 License
8
+ #
9
+
10
+ # the purpose of this file is just to allow both
11
+ # <em>require "micromidi"</em>
12
+ # and
13
+ # <em>require "midi"</em>
14
+
15
+ require 'micromidi'
data/test/helper.rb ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ dir = File.dirname(File.expand_path(__FILE__))
4
+ $LOAD_PATH.unshift dir + '/../lib'
5
+
6
+ require 'test/unit'
7
+ require 'midi'
8
+
9
+ module TestHelper
10
+
11
+ def self.select_devices
12
+ $test_device ||= {}
13
+ { :input => UniMIDI::Input.all, :output => UniMIDI::Output.all }.each do |type, devs|
14
+ puts ""
15
+ puts "select an #{type.to_s}..."
16
+ while $test_device[type].nil?
17
+ devs.each do |device|
18
+ puts device.pretty_name
19
+ end
20
+ selection = $stdin.gets.chomp
21
+ if selection != ""
22
+ selection = selection.to_i
23
+ $test_device[type] = devs.find { |d| d.id == selection }
24
+ puts "selected #{selection} for #{type.to_s}" unless $test_device[type]
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ TestHelper.select_devices
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class CompositeTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_play
12
+ m = MicroMIDI.message
13
+ start = Time.now
14
+ msg = m.play "C0", 0.5
15
+
16
+ finish = Time.now
17
+ dif = finish - start
18
+ assert_equal(true, dif >= 0.5)
19
+
20
+ assert_equal(NoteOn, msg.class)
21
+ assert_equal(12, msg.note)
22
+ assert_equal(0, msg.channel)
23
+ assert_equal(2, m.state.output_cache.size)
24
+
25
+ off_msg = m.state.output_cache.last[:message]
26
+ assert_equal(NoteOff, off_msg.class)
27
+ assert_equal(12, off_msg.note)
28
+ assert_equal(0, off_msg.channel)
29
+ end
30
+
31
+ def test_all_off
32
+
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class ContextTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_no_block
12
+ m = MIDI::IO.new
13
+ msg = m.note "C0"
14
+ assert_equal(NoteOn, msg.class)
15
+ assert_equal(12, msg.note)
16
+ assert_equal(0, msg.channel)
17
+ end
18
+
19
+ def test_repeat
20
+ m = MicroMIDI.message
21
+ msg = m.note "C0"
22
+ assert_equal(NoteOn, msg.class)
23
+ assert_equal(12, msg.note)
24
+ assert_equal(0, msg.channel)
25
+
26
+ r_msg = m.repeat
27
+ assert_equal(NoteOn, r_msg.class)
28
+ assert_equal(12, r_msg.note)
29
+ assert_equal(0, r_msg.channel)
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class EffectTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include TestHelper
9
+
10
+ def test_high_pass_note_reject
11
+ m = MicroMIDI.message
12
+ msg = m.note "C0"
13
+ outp = m.hpf msg, :note, 20
14
+ assert_equal(12, msg.note)
15
+ assert_equal(nil, outp)
16
+ end
17
+
18
+ def test_high_pass_note_accept
19
+ m = MicroMIDI.message
20
+ msg = m.note "C4"
21
+ outp = m.hpf msg, :note, 20
22
+ assert_equal(60, msg.note)
23
+ assert_equal(msg, outp)
24
+ end
25
+
26
+ def test_low_pass_note_reject
27
+ m = MicroMIDI.message
28
+ msg = m.note "C4"
29
+ outp = m.lpf msg, :note, 50
30
+ assert_equal(60, msg.note)
31
+ assert_equal(nil, outp)
32
+ end
33
+
34
+ def test_low_pass_note_accept
35
+ m = MicroMIDI.message
36
+ msg = m.note "C4"
37
+ outp = m.lp msg, :note, 100
38
+ assert_equal(60, msg.note)
39
+ assert_equal(msg, outp)
40
+ end
41
+
42
+ def test_band_pass_note_reject
43
+ m = MicroMIDI.message
44
+ msg = m.note "C4"
45
+ outp = m.bpf msg, :note, (20..50)
46
+ assert_equal(60, msg.note)
47
+ assert_equal(nil, outp)
48
+ end
49
+
50
+ def test_band_pass_note_accept
51
+ m = MicroMIDI.message
52
+ msg = m.note "C4"
53
+ outp = m.bp msg, :note, (20..100)
54
+ assert_equal(60, msg.note)
55
+ assert_equal(msg, outp)
56
+ end
57
+
58
+ def test_notch_note_reject
59
+ m = MicroMIDI.message
60
+ msg = m.note "C4"
61
+ outp = m.nf msg, :note, (20..70)
62
+ assert_equal(60, msg.note)
63
+ assert_equal(nil, outp)
64
+ end
65
+
66
+ def test_notch_note_accept
67
+ m = MicroMIDI.message
68
+ msg = m.note "C4"
69
+ outp = m.nf msg, :note, (20..50)
70
+ assert_equal(60, msg.note)
71
+ assert_equal(msg, outp)
72
+ end
73
+
74
+ def test_multiband_note_reject
75
+ m = MicroMIDI.message
76
+ msg = m.note "C4"
77
+ outp = m.f msg, :note, [(20..30), (40..50)]
78
+ assert_equal(60, msg.note)
79
+ assert_equal(nil, outp)
80
+ end
81
+
82
+ def test_multiband_note_accept
83
+ m = MicroMIDI.message
84
+ msg = m.note "C4"
85
+ outp = m.mbf msg, :note, [(20..30), (50..70)]
86
+ assert_equal(60, msg.note)
87
+ assert_equal(msg, outp)
88
+ end
89
+
90
+ def test_multinotch_note_reject
91
+ m = MicroMIDI.message
92
+ msg = m.note "C4"
93
+ outp = m.mbf msg, :note, [(20..30), (55..65)], :reject => true
94
+ assert_equal(60, msg.note)
95
+ assert_equal(nil, outp)
96
+ end
97
+
98
+ def test_multinotch_note_accept
99
+ m = MicroMIDI.message
100
+ msg = m.note "C4"
101
+ outp = m.mbf msg, :note, [(20..30), (40..50)], :reject => true
102
+ assert_equal(60, msg.note)
103
+ assert_equal(msg, outp)
104
+ end
105
+
106
+ def test_limit_low
107
+ m = MicroMIDI.message
108
+ msg = m.note "C0"
109
+ outp = m.limit msg, :note, (20..50)
110
+ assert_equal(20, msg.note)
111
+ end
112
+
113
+ def test_limit_high
114
+ m = MicroMIDI.message
115
+ msg = m.note "C6"
116
+ outp = m.limit msg, :note, (20..50)
117
+ assert_equal(50, msg.note)
118
+ end
119
+
120
+ def test_transpose_note_up
121
+ m = MicroMIDI.message
122
+ msg = m.note "C4"
123
+ outp = m.transpose msg, :note, 5
124
+ assert_equal(65, msg.note)
125
+ end
126
+
127
+ def test_transpose_velocity_down
128
+ m = MicroMIDI.message
129
+ msg = m.note "C4", :velocity => 82
130
+ outp = m.transpose msg, :velocity, -10
131
+ assert_equal(72, msg.velocity)
132
+ end
133
+
134
+ end
135
+
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class InputTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_thru_listeners
12
+ m = MicroMIDI.message($test_device[:input].open)
13
+ m.thru
14
+ assert_equal(0, m.state.listeners.size)
15
+ assert_equal(1, m.state.thru_listeners.size)
16
+ assert_equal(MIDIEye::Listener, m.state.thru_listeners.first.class)
17
+ end
18
+
19
+ def test_thru_unless
20
+ end
21
+
22
+ end
23
+
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class MessageTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_cc
12
+ m = MicroMIDI.message
13
+ msg = m.cc 16, 12
14
+ assert_equal(ControlChange, msg.class)
15
+ assert_equal(16, msg.index)
16
+ assert_equal(12, msg.value)
17
+ end
18
+
19
+ def test_channel_aftertouch
20
+ m = MicroMIDI::IO.new
21
+ msg = m.channel_aftertouch 2, :channel => 1
22
+ assert_equal(ChannelAftertouch, msg.class)
23
+ assert_equal(1, msg.channel)
24
+ assert_equal(2, msg.value)
25
+ end
26
+
27
+ def test_poly_aftertouch
28
+ m = MicroMIDI::IO.new
29
+ msg = m.poly_aftertouch 64, 2, :channel => 1
30
+ assert_equal(PolyphonicAftertouch, msg.class)
31
+ assert_equal(1, msg.channel)
32
+ assert_equal(64, msg.note)
33
+ assert_equal(2, msg.value)
34
+ end
35
+
36
+ def test_pitch_bend
37
+ m = MicroMIDI::IO.new
38
+ msg = m.pitch_bend 64, 2, :channel => 1
39
+ assert_equal(PitchBend, msg.class)
40
+ assert_equal(1, msg.channel)
41
+ assert_equal(64, msg.low)
42
+ assert_equal(2, msg.high)
43
+ end
44
+
45
+ def test_note_off
46
+ m = MicroMIDI.message
47
+ msg = m.note_off 13, :channel => 9, :velocity => 80
48
+ assert_equal(NoteOff, msg.class)
49
+ assert_equal(13, msg.note)
50
+ assert_equal(9, msg.channel)
51
+ assert_equal(80, msg.velocity)
52
+ end
53
+
54
+ def test_note_on_string
55
+ m = MicroMIDI.message
56
+ msg = m.note "C0", :velocity => 94
57
+ assert_equal(NoteOn, msg.class)
58
+ assert_equal(12, msg.note)
59
+ assert_equal(94, msg.velocity)
60
+ end
61
+
62
+ def test_note_on_string_no_octave
63
+ m = MicroMIDI.message
64
+ msg = m.note "C", :velocity => 94
65
+ assert_equal(NoteOn, msg.class)
66
+ assert_equal(36, msg.note)
67
+ assert_equal(94, msg.velocity)
68
+ end
69
+
70
+ def test_note_on_int
71
+ m = MicroMIDI.message
72
+ msg = m.note 12, :channel => 3
73
+ assert_equal(NoteOn, msg.class)
74
+ assert_equal(12, msg.note)
75
+ assert_equal(3, msg.channel)
76
+ end
77
+
78
+ def test_note_on_symbol
79
+ m = MicroMIDI.message
80
+ msg = m.note :C0
81
+ assert_equal(NoteOn, msg.class)
82
+ assert_equal(12, msg.note)
83
+ assert_equal(100, msg.velocity)
84
+ end
85
+
86
+ def test_note_on_symbol_no_octave
87
+ m = MicroMIDI.message
88
+ msg = m.note :C
89
+ assert_equal(NoteOn, msg.class)
90
+ assert_equal(36, msg.note)
91
+ assert_equal(100, msg.velocity)
92
+ end
93
+
94
+ def test_parse
95
+ m = MicroMIDI.message
96
+ msg = m.parse "906040"
97
+ assert_equal(NoteOn, msg.class)
98
+ assert_equal(96, msg.note)
99
+ assert_equal(0, msg.channel)
100
+ assert_equal(64, msg.velocity)
101
+ end
102
+
103
+ def test_program_change
104
+ m = MicroMIDI.message
105
+ msg = m.program_change 15
106
+ assert_equal(ProgramChange, msg.class)
107
+ assert_equal(15, msg.program)
108
+ end
109
+
110
+ def test_off
111
+ m = MicroMIDI.message
112
+ msg = m.note "C0", :channel => 3
113
+ assert_equal(NoteOn, msg.class)
114
+ assert_equal(12, msg.note)
115
+ assert_equal(3, msg.channel)
116
+ off_msg = m.off
117
+ assert_equal(NoteOff, off_msg.class)
118
+ assert_equal(12, off_msg.note)
119
+ assert_equal(3, off_msg.channel)
120
+ end
121
+
122
+ end
123
+
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class OutputTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_auto_output
12
+ m = MicroMIDI.message($test_device[:output].open)
13
+ assert_equal(true, m.state.auto_output)
14
+ m.output false
15
+ assert_equal(false, m.state.auto_output)
16
+ m.output true
17
+ assert_equal(true, m.state.auto_output)
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helper'
4
+
5
+ class StateTest < Test::Unit::TestCase
6
+
7
+ include MicroMIDI
8
+ include MIDIMessage
9
+ include TestHelper
10
+
11
+ def test_output_cache
12
+ m = MicroMIDI.message
13
+ cache = m.state.output_cache
14
+
15
+ m.note "C0"
16
+ assert_equal(1, cache.size)
17
+
18
+ m.note "C3"
19
+ assert_equal(2, cache.size)
20
+ end
21
+
22
+ def test_start_time
23
+ t1 = Time.now.to_f
24
+ m = MicroMIDI.message
25
+ t2 = Time.now.to_f
26
+ t = m.state.start_time
27
+ assert_equal(true, t1 < t)
28
+ assert_equal(true, t < t2)
29
+ end
30
+
31
+ end
32
+