micromidi 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aebc5e4f8bffb84656b7b662122cdae4c136c8e3
4
- data.tar.gz: 9b6a8f43960f1a94785cbd4d5dfe1b7754bb7b5f
3
+ metadata.gz: f2f1df337f1568e1e5b327664ee14734eae8095a
4
+ data.tar.gz: 45fa44750f71f646414883b7103ccadf9162c7d6
5
5
  SHA512:
6
- metadata.gz: be3f0f5d0872e7db2f60b30495df785c099aa56ecb890ff677ba0cdf53ad6ff99aea9a55492756d7f3a9d6d40922f3eb6b0baf8bb50120925a4ad9656b497ba0
7
- data.tar.gz: 950635b62998a768e13614efb3c02e472b0da4439ed27ba3c8a576999b376f3f92e075db07a9abd9dac3206032a94b913168122752a29625499aa3b0848fcdb0
6
+ metadata.gz: 9afb9c4ef330f7cb29b9baf02d37371055487f27f6833f46d99dc46c81161fe0dba982f27572f00422b8dfa20566d6901fbd34069df83ac65399c9e9e38e3a8d
7
+ data.tar.gz: fa2eb27bdb3162c12a8fac1f6ba72edba97e5e1e6891a43df5c7ca20afe8f006b64ebb41239e544d15bc6495c5fafb9f0e896060b6ab7015c3ebfdc206899e25
data/lib/micromidi.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # micromidi
2
+ # MicroMIDI
3
3
  #
4
4
  # A Ruby DSL for MIDI
5
5
  #
@@ -14,46 +14,9 @@ require "midi-fx"
14
14
  require "midi-message"
15
15
  require "unimidi"
16
16
 
17
- module MicroMIDI
18
-
19
- VERSION = "0.1.2"
20
-
21
- module Instructions
22
- end
23
-
24
- def self.new(*a, &block)
25
- message(*a, &block)
26
- end
27
-
28
- def self.message(*args, &block)
29
- ins, outs = *process_devices(args)
30
- MicroMIDI::Context.new(ins, outs, &block)
31
- end
32
- class << self
33
- alias_method :using, :message
34
- end
35
-
36
- module IO
37
-
38
- def self.new(*args, &block)
39
- MicroMIDI.message(*args, &block)
40
- end
41
-
42
- end
43
-
44
- private
45
-
46
- def self.process_devices(args)
47
- ins = args.find_all { |d| d.respond_to?(:type) && d.type == :input && d.respond_to?(:gets) }
48
- outs = args.find_all { |d| d.respond_to?(:puts) }
49
- [ins, outs]
50
- end
51
-
52
- end
53
- MIDI = MicroMIDI
54
-
55
17
  # modules
56
18
  require "micromidi/instructions/composite"
19
+ require "micromidi/module_methods"
57
20
 
58
21
  # classes
59
22
  require "micromidi/context"
@@ -67,3 +30,11 @@ require "micromidi/instructions/sysex"
67
30
 
68
31
  # extension
69
32
  require "micromidi/instructions/shorthand"
33
+
34
+ module MicroMIDI
35
+
36
+ VERSION = "0.1.3"
37
+
38
+ end
39
+ MIDI = MicroMIDI
40
+
@@ -25,37 +25,50 @@ module MicroMIDI
25
25
  edit(&block) unless block.nil?
26
26
  end
27
27
 
28
- # open a block for editing/live coding in this Context
28
+ # Open a block for editing/live coding in this Context
29
29
  def edit(&block)
30
- self.instance_eval(&block)
30
+ instance_eval(&block)
31
31
  end
32
32
 
33
+ # Repeat the last instruction in the history
33
34
  def repeat
34
- self.send(@state.last_command[:method], *@state.last_command[:args]) unless @state.last_command.nil?
35
+ send(@state.last_command[:method], *@state.last_command[:args]) unless @state.last_command.nil?
35
36
  end
36
37
 
37
- def method_missing(m, *a, &b)
38
- delegated = false
39
- outp = nil
40
- options = a.last.kind_of?(Hash) ? a.last : {}
41
- do_output = options[:output] || true
42
- [@instructions[:sysex], @instructions[:message], @instructions[:process]].each do |dsl|
43
- if dsl.respond_to?(m)
44
- msg = dsl.send(m, *a, &b)
45
- outp = @state.auto_output && do_output ? @instructions[:output].output(msg) : msg
46
- delegated = true
38
+ # Delegates a command to one of the instruction classes
39
+ def method_missing(method, *args, &block)
40
+ results = delegate(method, args, &block)
41
+ if results.empty?
42
+ super
43
+ else
44
+ messages = results.map do |result|
45
+ @state.record(method, args, block, result[:message])
46
+ @instructions[:output].output(result[:message]) if output?(result[:instruction_type])
47
+ result[:message]
47
48
  end
49
+ messages.compact.first
48
50
  end
49
- unless delegated
50
- [@instructions[:input], @instructions[:output], @instructions[:sticky]].each do |dsl|
51
- if dsl.respond_to?(m)
52
- outp = dsl.send(m, *a, &b)
53
- delegated = true
54
- end
51
+ end
52
+
53
+ private
54
+
55
+ # Should a message that resulted from the given instruction type be outputted?
56
+ def output?(instruction_type)
57
+ @state.auto_output && [:sysex, :message, :process].include?(instruction_type)
58
+ end
59
+
60
+ # Delegate a command
61
+ def delegate(method, args, &block)
62
+ results = @instructions.map do |key, instruction|
63
+ if instruction.respond_to?(method)
64
+ message = instruction.send(method, *args, &block)
65
+ {
66
+ :instruction_type => key,
67
+ :message => message
68
+ }
55
69
  end
56
70
  end
57
- @state.record(m, a, b, outp)
58
- delegated ? outp : super
71
+ results.compact
59
72
  end
60
73
 
61
74
  end
@@ -5,31 +5,24 @@ module MicroMIDI
5
5
  module Composite
6
6
 
7
7
  #
8
- # plays a note or notes, for a certain duration.
8
+ # Plays a note or notes, for a certain duration.
9
9
  #
10
- # the first argument must be a note name (String), MIDIMessage::NoteOn object, or array of either
10
+ # The first argument must be a note name (String), MIDIMessage::NoteOn object, or array of either
11
11
  # the last argument must be a Numeric (representing the duration)
12
12
  #
13
- # additional arguments should be note names or MIDIMessage::NoteOn objects and will
14
- # be played as a chord with the first argument
13
+ # Additional arguments should be note names or MIDIMessage::NoteOn objects and will
14
+ # be played as a chord with the first argument.
15
15
  #
16
16
  def play(*args)
17
- raise "last argument must be a Numeric duration" unless args.last.kind_of?(Numeric)
17
+ raise "Last argument must be a Numeric duration" unless args.last.kind_of?(Numeric)
18
18
 
19
19
  duration = args.pop
20
20
  note_or_notes = [args].flatten
21
-
22
- msgs = note_or_notes.map do |n|
23
- case n
24
- when Numeric, String then note(n)
25
- when MIDIMessage then n
26
- end
27
- end
28
-
21
+ messages = as_note_messages(note_or_notes)
29
22
  sleep(duration)
30
- msgs.each { |msg| note_off(msg.note, :channel => msg.channel, :velocity => msg.velocity) }
23
+ send_note_offs(messages)
31
24
 
32
- msgs.size > 1 ? msgs : msgs.first
25
+ messages.count > 1 ? messages : messages.first
33
26
  end
34
27
 
35
28
  # sends a note off message for every note on every channel
@@ -42,6 +35,23 @@ module MicroMIDI
42
35
  true
43
36
  end
44
37
  alias_method :quiet!, :all_off
38
+
39
+ private
40
+
41
+ def send_note_offs(messages)
42
+ messages.each do |message|
43
+ note_off(message.note, :channel => message.channel, :velocity => message.velocity)
44
+ end
45
+ end
46
+
47
+ def as_note_messages(note_or_notes)
48
+ note_or_notes.map do |note|
49
+ case note
50
+ when Numeric, String then note(note)
51
+ when MIDIMessage then note
52
+ end
53
+ end
54
+ end
45
55
 
46
56
  end
47
57
 
@@ -3,18 +3,21 @@ module MicroMIDI
3
3
  module Instructions
4
4
 
5
5
  class Input
6
-
7
- include MIDIMessage
8
-
6
+
9
7
  def initialize(state)
10
8
  @state = state
11
9
  end
12
10
 
13
11
  # bind an event that will be called every time a message is received
14
- def receive(*a, &block)
15
- options = a.last.kind_of?(Hash) ? a.pop : {}
16
- match = a.empty? ? nil : { :class => msg_classes(a) }
17
- listener(match, options) { |event| yield(event[:message], event[:timestamp]) }
12
+ def receive(*args, &block)
13
+ message_options = args.dup
14
+ options = message_options.last.kind_of?(Hash) ? message_options.pop : {}
15
+ unless message_options.empty?
16
+ match = { :class => message_classes(message_options) }
17
+ end
18
+ listener(match, options) do |event|
19
+ yield(event[:message], event[:timestamp])
20
+ end
18
21
  end
19
22
  alias_method :gets, :receive
20
23
  alias_method :handle, :receive
@@ -22,10 +25,13 @@ module MicroMIDI
22
25
  alias_method :listen_for, :receive
23
26
  alias_method :when_receive, :receive
24
27
 
25
- def receive_unless(*a, &block)
26
- options = a.last.kind_of?(Hash) ? a.pop : {}
27
- match = { :class => msg_classes(a) }
28
- listener(nil, options) { |event| yield(event[:message], event[:timestamp]) unless match.include?(event[:message].class) }
28
+ def receive_unless(*args, &block)
29
+ message_options = args.dup
30
+ options = message_options.last.kind_of?(Hash) ? message_options.pop : {}
31
+ match = message_classes(message_options)
32
+ listener(nil, options) do |event|
33
+ yield(event[:message], event[:timestamp]) unless match.include?(event[:message].class)
34
+ end
29
35
  end
30
36
  alias_method :handle_unless, :receive_unless
31
37
  alias_method :listen_unless, :receive_unless
@@ -38,22 +44,22 @@ module MicroMIDI
38
44
  end
39
45
 
40
46
  # send input messages thru to the outputs if it has a specific class
41
- def thru_if(*a)
42
- a.last.kind_of?(Hash) ? a.last[:thru] = true : a.push({ :thru => true })
43
- receive(*a) { |message, timestamp| output(message) }
47
+ def thru_if(*args)
48
+ receive_options = thru_options(args)
49
+ receive(*receive_options) { |message, timestamp| output(message) }
44
50
  end
45
51
 
46
52
  # send input messages thru to the outputs unless of a specific class
47
- def thru_unless(*a)
48
- a.last.kind_of?(Hash) ? a.last[:thru] = true : a.push({ :thru => true })
49
- receive_unless(*a) { |message, timestamp| output(message) }
53
+ def thru_unless(*args)
54
+ receive_options = thru_options(args)
55
+ receive_unless(*receive_options) { |message, timestamp| output(message) }
50
56
  end
51
57
 
52
58
  # like <em>thru_unless</em> except a block can be passed that will be called when
53
59
  # notes specified as the <em>unless</em> arrive
54
- def thru_except(*a, &block)
55
- thru_unless(*a)
56
- receive(*a, &block)
60
+ def thru_except(*args, &block)
61
+ thru_unless(*args)
62
+ receive(*args, &block)
57
63
  end
58
64
 
59
65
  # wait for input on the last input passed in
@@ -69,38 +75,56 @@ module MicroMIDI
69
75
 
70
76
  protected
71
77
 
72
- def listener(match = {}, options = {}, &block)
78
+ def listener(match, options = {}, &block)
73
79
  inputs = options[:from] || @state.inputs
74
- thru = options[:thru] || false
80
+ do_thru = options.fetch(:thru, false)
81
+ should_start = options.fetch(:start, true)
75
82
  match ||= {}
76
- inputs.each do |input|
77
- listener = MIDIEye::Listener.new(input)
78
- listener.listen_for(match, &block)
79
- if thru
80
- @state.thru_listeners.each { |l| l.stop }
81
- @state.thru_listeners.clear
82
- @state.thru_listeners << listener
83
- else
84
- @state.listeners << listener
85
- end
86
- listener.start(:background => true) unless !options[:start].nil? && !options[:start]
83
+
84
+ listeners = inputs.map { |input| initialize_listener(input, match, do_thru, &block) }
85
+ if should_start
86
+ listeners.each { |listener| listener.start(:background => true) }
87
87
  end
88
88
  end
89
89
 
90
90
  private
91
91
 
92
- def msg_classes(list)
92
+ def initialize_listener(input, match, do_thru, &block)
93
+ listener = MIDIEye::Listener.new(input)
94
+ listener.listen_for(match, &block)
95
+ if do_thru
96
+ @state.thru_listeners.each(&:stop)
97
+ @state.thru_listeners.clear
98
+ @state.thru_listeners << listener
99
+ else
100
+ @state.listeners << listener
101
+ end
102
+ listener
103
+ end
104
+
105
+ # The options for using thru
106
+ def thru_options(args)
107
+ receive_options = args.dup
108
+ if receive_options.last.kind_of?(Hash)
109
+ receive_options.last[:thru] = true
110
+ else
111
+ receive_options << { :thru => true }
112
+ end
113
+ receive_options
114
+ end
115
+
116
+ def message_classes(list)
93
117
  list.map do |type|
94
118
  case type
95
- when :aftertouch, :pressure, :aft then [ChannelAftertouch, PolyphonicAftertouch]
96
- when :channel_aftertouch, :channel_pressure, :ca, :cp then ChannelAftertouch
97
- when :control_change, :cc, :c then ControlChange
98
- when :note, :n then [NoteOn, NoteOff]
99
- when :note_on, :nn then NoteOn
100
- when :note_off, :no, :off then NoteOff
101
- when :pitch_bend, :pb then PitchBend
102
- when :polyphonic_aftertouch, :poly_aftertouch, :poly_pressure, :polyphonic_pressure, :pa, :pp then PolyphonicAftertouch
103
- when :program_change, :pc, :p then ProgramChange
119
+ when :aftertouch, :pressure, :aft then [MIDIMessage::ChannelAftertouch, MIDIMessage::PolyphonicAftertouch]
120
+ when :channel_aftertouch, :channel_pressure, :ca, :cp then MIDIMessage::ChannelAftertouch
121
+ when :control_change, :cc, :c then MIDIMessage::ControlChange
122
+ when :note, :n then [MIDIMessage::NoteOn, MIDIMessage::NoteOff]
123
+ when :note_on, :nn then MIDIMessage::NoteOn
124
+ when :note_off, :no, :off then MIDIMessage::NoteOff
125
+ when :pitch_bend, :pb then MIDIMessage::PitchBend
126
+ when :polyphonic_aftertouch, :poly_aftertouch, :poly_pressure, :polyphonic_pressure, :pa, :pp then MIDIMessage::PolyphonicAftertouch
127
+ when :program_change, :pc, :p then MIDIMessage::ProgramChange
104
128
  end
105
129
  end.flatten.compact
106
130
  end
@@ -3,41 +3,33 @@ module MicroMIDI
3
3
  module Instructions
4
4
 
5
5
  class Message
6
-
7
- include MIDIMessage
8
6
 
9
7
  def initialize(state)
10
8
  @state = state
11
9
  end
12
10
 
13
11
  # create a control change message
14
- def control_change(id, value, opts = {})
15
- props = @state.message_properties(opts, :channel)
16
- id.kind_of?(Numeric) ? ControlChange.new(props[:channel], id, value) : ControlChange[id].new(props[:channel], value)
12
+ def control_change(id, value, options = {})
13
+ properties = @state.message_properties(options, :channel)
14
+ if id.kind_of?(Numeric)
15
+ MIDIMessage::ControlChange.new(properties[:channel], id, value)
16
+ else
17
+ MIDIMessage::ControlChange[id].new(properties[:channel], value)
18
+ end
17
19
  end
18
20
 
19
21
  # create a note message
20
- def note(id, opts = {})
21
- props = @state.message_properties(opts, :channel, :velocity)
22
- note = if id.kind_of?(Numeric)
23
- NoteOn.new(props[:channel], id, props[:velocity])
24
- elsif id.kind_of?(String) || id.kind_of?(Symbol)
25
- note_string = parse_note_name(id)
26
- NoteOn[note_string].new(props[:channel], props[:velocity])
27
- end
22
+ def note(id, options = {})
23
+ properties = @state.message_properties(options, :channel, :velocity)
24
+ note = note_message(MIDIMessage::NoteOn, id, properties)
28
25
  @state.last_note = note
29
26
  note
30
27
  end
31
28
 
32
29
  # create a note off message
33
- def note_off(id, opts = {})
34
- props = @state.message_properties(opts, :channel, :velocity)
35
- if id.kind_of?(Numeric)
36
- NoteOff.new(props[:channel], id, props[:velocity])
37
- elsif id.kind_of?(String) || id.kind_of?(Symbol)
38
- note_string = parse_note_name(id)
39
- NoteOff[parse_note_name(id)].new(props[:channel], props[:velocity])
40
- end
30
+ def note_off(id, options = {})
31
+ properties = @state.message_properties(options, :channel, :velocity)
32
+ note_message(MIDIMessage::NoteOff, id, properties)
41
33
  end
42
34
 
43
35
  # create a MIDI message from a byte string, array of bytes, or list of bytes
@@ -46,37 +38,37 @@ module MicroMIDI
46
38
  end
47
39
 
48
40
  # create a program change message
49
- def program_change(program, opts = {})
50
- props = @state.message_properties(opts, :channel)
51
- MIDIMessage::ProgramChange.new(props[:channel], program)
41
+ def program_change(program, options = {})
42
+ properties = @state.message_properties(options, :channel)
43
+ MIDIMessage::ProgramChange.new(properties[:channel], program)
52
44
  end
53
45
 
54
46
  # create a note-off message from the last note-on message
55
47
  def off
56
- o = @state.last_note.to_note_off unless @state.last_note.nil?
48
+ note_off = @state.last_note.to_note_off unless @state.last_note.nil?
57
49
  @state.last_note = nil
58
- o
50
+ note_off
59
51
  end
60
52
 
61
53
  # create a channel pressure message
62
- def channel_aftertouch(value, opts = {})
63
- props = @state.message_properties(opts, :channel)
64
- MIDIMessage::ChannelAftertouch.new(props[:channel], value)
54
+ def channel_aftertouch(value, options = {})
55
+ properties = @state.message_properties(options, :channel)
56
+ MIDIMessage::ChannelAftertouch.new(properties[:channel], value)
65
57
  end
66
58
  alias_method :channel_pressure, :channel_aftertouch
67
59
 
68
60
  # create a poly pressure message
69
- def polyphonic_aftertouch(note, value, opts = {})
70
- props = @state.message_properties(opts, :channel)
71
- MIDIMessage::PolyphonicAftertouch.new(props[:channel], note, value)
61
+ def polyphonic_aftertouch(note, value, options = {})
62
+ properties = @state.message_properties(options, :channel)
63
+ MIDIMessage::PolyphonicAftertouch.new(properties[:channel], note, value)
72
64
  end
73
65
  alias_method :poly_aftertouch, :polyphonic_aftertouch
74
66
  alias_method :polyphonic_pressure, :polyphonic_aftertouch
75
67
  alias_method :poly_pressure, :polyphonic_aftertouch
76
68
 
77
- def pitch_bend(low, high, opts = {})
78
- props = @state.message_properties(opts, :channel)
79
- MIDIMessage::PitchBend.new(props[:channel], low, high)
69
+ def pitch_bend(low, high, options = {})
70
+ properties = @state.message_properties(options, :channel)
71
+ MIDIMessage::PitchBend.new(properties[:channel], low, high)
80
72
  end
81
73
  alias_method :bend, :pitch_bend
82
74
  alias_method :pitchbend, :pitch_bend
@@ -84,11 +76,23 @@ module MicroMIDI
84
76
  protected
85
77
 
86
78
  def parse_note_name(name)
87
- name = name.to_s #ensure that name is a string
88
- string_opts = { :octave => name.scan(/-?\d\z/).first }
79
+ name = name.to_s
80
+ octave = name.scan(/-?\d\z/).first
81
+ string_options = { :octave => octave }
89
82
  note = name.split(/-?\d\z/).first
90
- string_props = @state.message_properties(string_opts, :octave)
91
- "#{note}#{string_props[:octave].to_s}"
83
+ string_properties = @state.message_properties(string_options, :octave)
84
+ "#{note}#{string_properties[:octave].to_s}"
85
+ end
86
+
87
+ private
88
+
89
+ def note_message(klass, id, properties)
90
+ if id.kind_of?(Numeric)
91
+ klass.new(properties[:channel], id, properties[:velocity])
92
+ elsif id.kind_of?(String) || id.kind_of?(Symbol)
93
+ note_name = parse_note_name(id)
94
+ klass[note_name].new(properties[:channel], properties[:velocity])
95
+ end
92
96
  end
93
97
 
94
98
  end
@@ -4,19 +4,32 @@ module MicroMIDI
4
4
 
5
5
  class Output
6
6
 
7
+ extend Forwardable
8
+
9
+ def_delegators :@state, :toggle_auto_output
10
+ alias_method :auto_output, :toggle_auto_output
11
+
12
+ # @param [State] state
7
13
  def initialize(state)
8
14
  @state = state
9
15
  end
10
16
 
11
- def output(msg)
12
- auto_output(msg) if msg === false || msg === true
13
- @state.outputs.each { |o| o.puts(msg) } unless msg.nil?
14
- msg
17
+ # Output a message or toggle the auto output mode
18
+ # @param [MIDIMessage, Boolean] message A MIDI message to output, or a boolean to toggle auto-output mode
19
+ # @return [BIDIMessage]
20
+ def output(message)
21
+ set_auto_output(message) if !!message === message # check for boolean
22
+ unless message.nil?
23
+ @state.outputs.each { |output| output.puts(message) }
24
+ end
25
+ message
15
26
  end
16
27
 
17
- # toggle mode where messages are automatically outputted
18
- def auto_output(mode = nil)
19
- mode.nil? ? @state.toggle_auto_output : @state.auto_output = mode
28
+ # Set mode where messages are automatically outputted
29
+ # @param [Boolean] is_on Whether to set the auto output mode to ON
30
+ # @return [Boolean]
31
+ def set_auto_output(is_on)
32
+ @state.auto_output = is_on
20
33
  end
21
34
 
22
35
  end
@@ -2,8 +2,8 @@ module MicroMIDI
2
2
 
3
3
  alias l loop
4
4
 
5
- class << self
6
- alias_method :m, :message
5
+ def self.m(*args, &block)
6
+ send(:message, *args, &block)
7
7
  end
8
8
 
9
9
  class Context
@@ -0,0 +1,34 @@
1
+ module MicroMIDI
2
+
3
+ def self.new(*args, &block)
4
+ message(*args, &block)
5
+ end
6
+
7
+ def self.message(*args, &block)
8
+ inputs = get_inputs(args)
9
+ outputs = get_outputs(args)
10
+ MicroMIDI::Context.new(inputs, outputs, &block)
11
+ end
12
+ class << self
13
+ alias_method :using, :message
14
+ end
15
+
16
+ module IO
17
+
18
+ def self.new(*args, &block)
19
+ MicroMIDI.message(*args, &block)
20
+ end
21
+
22
+ end
23
+
24
+ private
25
+
26
+ def self.get_inputs(args)
27
+ args.find_all { |device| device.respond_to?(:type) && device.type == :input && device.respond_to?(:gets) }
28
+ end
29
+
30
+ def self.get_outputs(args)
31
+ args.find_all { |device| device.respond_to?(:puts) }
32
+ end
33
+
34
+ end
@@ -2,7 +2,7 @@ module MicroMIDI
2
2
 
3
3
  class State
4
4
 
5
- Default = {
5
+ DEFAULT = {
6
6
  :channel => 0,
7
7
  :octave => 2,
8
8
  :velocity => 100
@@ -24,7 +24,14 @@ module MicroMIDI
24
24
  :start_time,
25
25
  :thru_listeners
26
26
 
27
- def initialize(ins, outs, options = {})
27
+ def initialize(inputs, outputs, options = {})
28
+ @inputs = inputs
29
+ @outputs = outputs
30
+
31
+ @channel = options[:channel] || DEFAULT[:channel]
32
+ @velocity = options[:velocity] || DEFAULT[:velocity]
33
+ @octave = options[:octave] || DEFAULT[:octave]
34
+
28
35
  @auto_output = true
29
36
  @last_command = nil
30
37
  @last_note = nil
@@ -33,19 +40,21 @@ module MicroMIDI
33
40
  @output_cache = []
34
41
  @start_time = Time.now.to_f
35
42
  @super_sticky = false
36
-
37
- @channel = options[:channel] || Default[:channel]
38
- @velocity = options[:velocity] || Default[:velocity]
39
- @octave = options[:octave] || Default[:octave]
40
-
41
- @inputs = ins
42
- @outputs = outs
43
43
  end
44
44
 
45
- def record(m, a, b, outp)
46
- ts = now
47
- @output_cache << { :message => outp, :timestamp => ts }
48
- @last_command = { :method => m, :args => a, :block => b, :timestamp => ts }
45
+ def record(method, args, block, output)
46
+ timestamp = now
47
+ message = {
48
+ :message => output,
49
+ :timestamp => timestamp
50
+ }
51
+ @output_cache << message
52
+ @last_command = {
53
+ :method => method,
54
+ :args => args,
55
+ :block => block,
56
+ :timestamp => timestamp
57
+ }
49
58
  end
50
59
 
51
60
  def toggle_super_sticky
@@ -56,12 +65,14 @@ module MicroMIDI
56
65
  @auto_output = !@auto_output
57
66
  end
58
67
 
59
- def message_properties(opts, *props)
68
+ def message_properties(options, *properties)
60
69
  output = {}
61
- props.each do |prop|
62
- output[prop] = opts[prop]
63
- self.send("#{prop.to_s}=", output[prop]) if !output[prop].nil? && (self.send(prop).nil? || @super_sticky)
64
- output[prop] ||= self.send(prop.to_s)
70
+ properties.each do |property|
71
+ output[property] = options[property]
72
+ if !output[property].nil? && (send(property).nil? || @super_sticky)
73
+ send("#{property.to_s}=", output[property])
74
+ end
75
+ output[property] ||= send(property.to_s)
65
76
  end
66
77
  output
67
78
  end
@@ -69,7 +80,7 @@ module MicroMIDI
69
80
  private
70
81
 
71
82
  def now
72
- ((Time.now.to_f - @start_time) * 1000)
83
+ (Time.now.to_f - @start_time) * 1000
73
84
  end
74
85
 
75
86
  end
data/lib/midi.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  #
2
- # micromidi
2
+ # MicroMIDI
3
3
  # A Ruby DSL for MIDI
4
4
  #
5
- # (c)2011 Ari Russo
5
+ # (c)2011-2014 Ari Russo
6
6
  # licensed under the Apache 2.0 License
7
7
  #
8
8
 
data/test/input_test.rb CHANGED
@@ -2,10 +2,6 @@ require "helper"
2
2
 
3
3
  class InputTest < Test::Unit::TestCase
4
4
 
5
- include MicroMIDI
6
- include MIDIMessage
7
- include TestHelper
8
-
9
5
  def test_thru_listeners
10
6
  m = MicroMIDI.message($test_device[:input].open)
11
7
  m.thru
data/test/sysex_test.rb CHANGED
@@ -2,56 +2,54 @@ require "helper"
2
2
 
3
3
  class SysexTest < Test::Unit::TestCase
4
4
 
5
- include MicroMIDI
6
5
  include MIDIMessage
7
- include TestHelper
8
6
 
9
7
  def test_command
10
8
  m = MicroMIDI.message
11
9
  m.sysex_node 0x41, :model_id => 0x42, :device_id => 0x10
12
- msg = m.sysex_command [0x40, 0x7F, 0x00], 0x00
13
- assert_equal(SystemExclusive::Command, msg.class)
14
- assert_equal([0x40, 0x7F, 0x00], msg.address)
15
- assert_equal(0, msg.data)
16
- assert_equal([0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x7F, 0x00, 0x00, 0x41, 0xF7], msg.to_bytes)
10
+ message = m.sysex_command [0x40, 0x7F, 0x00], 0x00
11
+ assert_equal(SystemExclusive::Command, message.class)
12
+ assert_equal([0x40, 0x7F, 0x00], message.address)
13
+ assert_equal(0, message.data)
14
+ assert_equal([0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x7F, 0x00, 0x00, 0x41, 0xF7], message.to_bytes)
17
15
  end
18
16
 
19
17
  def test_request
20
18
  m = MicroMIDI.message
21
19
  m.sysex_node 0x41, :model_id => 0x42, :device_id => 0x10
22
- msg = m.sysex_request [0x40, 0x7F, 0x00], 0x02
23
- assert_equal(SystemExclusive::Request, msg.class)
24
- assert_equal([0x40, 0x7F, 0x00], msg.address)
25
- assert_equal([0x0, 0x0, 0x02], msg.size)
26
- assert_equal([0xF0, 0x41, 0x10, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0x3F, 0xF7], msg.to_bytes)
20
+ message = m.sysex_request [0x40, 0x7F, 0x00], 0x02
21
+ assert_equal(SystemExclusive::Request, message.class)
22
+ assert_equal([0x40, 0x7F, 0x00], message.address)
23
+ assert_equal([0x0, 0x0, 0x02], message.size)
24
+ assert_equal([0xF0, 0x41, 0x10, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0x3F, 0xF7], message.to_bytes)
27
25
  end
28
26
 
29
27
  def test_message
30
28
  m = MicroMIDI.message
31
- msg = m.sysex_message [0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02]
32
- assert_equal(SystemExclusive::Message, msg.class)
33
- assert_equal([0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02], msg.data)
34
- assert_equal([0xF0, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0xF7], msg.to_bytes)
29
+ message = m.sysex_message [0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02]
30
+ assert_equal(SystemExclusive::Message, message.class)
31
+ assert_equal([0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02], message.data)
32
+ assert_equal([0xF0, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0xF7], message.to_bytes)
35
33
  end
36
34
 
37
35
  def test_message_with_node
38
36
  m = MicroMIDI.message
39
37
  m.sysex_node 0x41, :model_id => 0x42, :device_id => 0x10
40
- msg = m.sysex_message [0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02]
41
- assert_equal(SystemExclusive::Message, msg.class)
42
- assert_equal([0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02], msg.data)
43
- assert_equal([0xF0, 0x41, 0x10, 0x42, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0xF7], msg.to_bytes)
38
+ message = m.sysex_message [0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02]
39
+ assert_equal(SystemExclusive::Message, message.class)
40
+ assert_equal([0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02], message.data)
41
+ assert_equal([0xF0, 0x41, 0x10, 0x42, 0x42, 0x11, 0x40, 0x7F, 0x00, 0x0, 0x0, 0x02, 0xF7], message.to_bytes)
44
42
  end
45
43
 
46
44
  def test_no_model_id
47
45
  m = MicroMIDI.message
48
46
  m.sysex_node 0x41, :device_id => 0x10
49
- msg = m.sysex_command [0x40, 0x7F, 0x00], 0x00
50
- assert_equal(SystemExclusive::Command, msg.class)
51
- assert_equal([0x41, 0x10], msg.node.to_a)
52
- assert_equal([0x40, 0x7F, 0x00], msg.address)
53
- assert_equal(0, msg.data)
54
- assert_equal([0xF0, 0x41, 0x10, 0x12, 0x40, 0x7F, 0x00, 0x00, 0x41, 0xF7], msg.to_bytes)
47
+ message = m.sysex_command [0x40, 0x7F, 0x00], 0x00
48
+ assert_equal(SystemExclusive::Command, message.class)
49
+ assert_equal([0x41, 0x10], message.node.to_a)
50
+ assert_equal([0x40, 0x7F, 0x00], message.address)
51
+ assert_equal(0, message.data)
52
+ assert_equal([0xF0, 0x41, 0x10, 0x12, 0x40, 0x7F, 0x00, 0x00, 0x41, 0xF7], message.to_bytes)
55
53
  end
56
54
 
57
55
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micromidi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
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-09-05 00:00:00.000000000 Z
11
+ date: 2014-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: midi-eye
@@ -103,6 +103,7 @@ files:
103
103
  - lib/micromidi/instructions/shorthand.rb
104
104
  - lib/micromidi/instructions/sticky.rb
105
105
  - lib/micromidi/instructions/sysex.rb
106
+ - lib/micromidi/module_methods.rb
106
107
  - lib/micromidi/state.rb
107
108
  - lib/midi.rb
108
109
  - test/composite_test.rb