micromidi 0.1.2 → 0.1.3

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 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