mmplayer 0.0.1 → 0.0.2

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: b444046bc6129a272ad1354fd79e0226d3fed0f6
4
- data.tar.gz: 7a58cbaec278585178e5ea420e3be977711a5f65
3
+ metadata.gz: eaf5bf960208966f12d484c199d7146229f81f4f
4
+ data.tar.gz: dc4d8cfbaa2f8554e5f9bd97cbc05be74482f75c
5
5
  SHA512:
6
- metadata.gz: 7d73ce2e7db56b04f05bde2ce3a713a0b15cb6ed37f944d6d9de8d45859ad6e70265c3f818056aa6e5e8b70f536ae64f265301e39b2986829c0f7080b26ba2aa
7
- data.tar.gz: 137bf592cad461210938a051ffad361b48019a55d87a788f76a48bdde80cd767c3729238fcb9c983c5094e44337bef934a13eeed852d1a57799e1ab483eb6689
6
+ metadata.gz: c269438f243f8a018f7382a39eecf518308162cfc27c27cf3dbda806fe2b9f0cf3a4c0b83533279b5a755305ab76f6f15352a5bac2f1af2471f9e0ed4f5bf6a6
7
+ data.tar.gz: 7d0dc1ca64157413bb42910dcbf7001e1ea874b074090c7125bf353b3bd817b4d559000de3193ba50b41bb29f28c7c1fc6459aec40076f64c60cacb350188002
data/README.md CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  Control [MPlayer](http://en.wikipedia.org/wiki/MPlayer) with MIDI
6
6
 
7
+ MPlayer is a free, cross-platform, command-line driven, highly configurable, (often) GUI-less open-source media player.
8
+
9
+ Enabling MPlayer to be controlled by MIDI opens up a host of possibilities for live video performance, media automation and more
10
+
11
+ This project provides a Ruby DSL to define realtime interactions between MIDI input and MPlayer
12
+
7
13
  ## Install
8
14
 
9
15
  You'll need to install MPlayer before using this. That can usually be accomplished with a package manager eg `brew install mplayer` depending on what OS you're using.
@@ -18,8 +24,6 @@ Or if you're using Bundler, add this to your Gemfile
18
24
 
19
25
  ## Usage
20
26
 
21
- MMplayer provides a Ruby DSL to define interactions between MIDI input and MPlayer
22
-
23
27
  ```ruby
24
28
  require "mmplayer"
25
29
 
@@ -47,9 +51,7 @@ An annotated breakdown of this example can be found [here](https://github.com/ar
47
51
 
48
52
  [The MPlayer Man Page](http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html#GENERAL OPTIONS) has a full list of MPlayer startup flags
49
53
 
50
- All MPlayer runtime commands enabled by the [mplayer-ruby](https://rubygems.org/gems/mplayer-ruby) project are available here too. (eg `seek` and `volume` in the example above)
51
-
52
- [The RDOC for mplayer-ruby](http://mplayer-ruby.rubyforge.org/mplayer-ruby/index.html) has a full list of runtime commands
54
+ All MPlayer runtime commands enabled by the [mplayer-ruby](https://rubygems.org/gems/mplayer-ruby) project are available here too. (eg `seek` and `volume` in the example above). [The RDOC for mplayer-ruby](http://mplayer-ruby.rubyforge.org/mplayer-ruby/index.html) has a full list of runtime commands
53
55
 
54
56
  ##Author
55
57
 
@@ -18,12 +18,13 @@ require "mmplayer/instructions/player"
18
18
 
19
19
  # classes
20
20
  require "mmplayer/context"
21
+ require "mmplayer/message_handler"
21
22
  require "mmplayer/midi"
22
23
  require "mmplayer/player"
23
24
 
24
25
  module MMPlayer
25
26
 
26
- VERSION = "0.0.1"
27
+ VERSION = "0.0.2"
27
28
 
28
29
  # Shortcut to Context constructor
29
30
  def self.new(*args, &block)
@@ -0,0 +1,84 @@
1
+ module MMPlayer
2
+
3
+ # Directs what should happen when messages are received
4
+ class MessageHandler
5
+
6
+ attr_reader :callback
7
+
8
+ def initialize
9
+ @callback = {
10
+ :cc => {},
11
+ :note => {},
12
+ :system => {}
13
+ }
14
+ end
15
+
16
+ # Add a callback for a given MIDI system message type
17
+ # @param [Symbol] type The MIDI message type (eg :note, :cc)
18
+ # @param [String, Symbol] key
19
+ # @param [Proc] callback The callback to execute when the given MIDI command is received
20
+ # @return [Hash]
21
+ def add_callback(type, key, &callback)
22
+ @callback[type][key] = callback
23
+ @callback[type]
24
+ end
25
+
26
+ # Process a message for the given channel
27
+ # @param [Fixnum, nil] channel
28
+ # @param [MIDIMessage] message
29
+ # @return [Boolean, nil]
30
+ def process(channel, message)
31
+ case message
32
+ when MIDIMessage::SystemRealtime then system_message(message)
33
+ else
34
+ channel_message(channel, message)
35
+ end
36
+ end
37
+
38
+ # Find and call a note received callback if it exists
39
+ # @param [MIDIMessage] message
40
+ # @return [Boolean, nil]
41
+ def note_message(message)
42
+ unless (callback = @callback[:note][message.note] || @callback[:note][message.name]).nil?
43
+ callback.call(message.velocity)
44
+ true
45
+ end
46
+ end
47
+
48
+ # Find and call a cc received callback if it exists
49
+ # @param [MIDIMessage] message
50
+ # @return [Boolean, nil]
51
+ def cc_message(message)
52
+ unless (callback = @callback[:cc][message.index] || @callback[:cc][message.name]).nil?
53
+ callback.call(message.value)
54
+ true
55
+ end
56
+ end
57
+
58
+ # Find and call a system message callback if it exists
59
+ # @param [MIDIMessage] message
60
+ # @return [Boolean, nil]
61
+ def system_message(message)
62
+ name = message.name.downcase.to_sym
63
+ unless (callback = @callback[:system][name]).nil?
64
+ callback.call
65
+ true
66
+ end
67
+ end
68
+
69
+ # Find and call a channel message callback if it exists for the given message and channel
70
+ # @param [Fixnum, nil] channel
71
+ # @param [MIDIMessage] message
72
+ # @return [Boolean, nil]
73
+ def channel_message(channel, message)
74
+ if channel.nil? || message.channel == channel
75
+ case message
76
+ when MIDIMessage::NoteOn then note_message(message)
77
+ when MIDIMessage::ControlChange then cc_message(message)
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -3,18 +3,14 @@ module MMPlayer
3
3
  # Wrapper for MIDI functionality
4
4
  class MIDI
5
5
 
6
- attr_reader :channel, :config, :listener
6
+ attr_reader :channel, :config, :listener, :message_handler
7
7
 
8
8
  # @param [UniMIDI::Input] input
9
9
  # @param [Hash] options
10
10
  # @option options [Fixnum] :receive_channel A MIDI channel to subscribe to. By default, responds to all
11
11
  def initialize(input, options = {})
12
12
  @channel = options[:receive_channel]
13
- @config = {
14
- :cc => {},
15
- :note => {},
16
- :system => {}
17
- }
13
+ @message_handler = MessageHandler.new
18
14
  @listener = MIDIEye::Listener.new(input)
19
15
  end
20
16
 
@@ -23,8 +19,7 @@ module MMPlayer
23
19
  # @param [Proc] callback The callback to execute when the given MIDI command is received
24
20
  # @return [Hash]
25
21
  def add_system_callback(command, &callback)
26
- @config[:system][command] = callback
27
- @config[:system]
22
+ @message_handler.add_callback(:system, command, &callback)
28
23
  end
29
24
 
30
25
  # Add a callback for a given MIDI note
@@ -32,8 +27,7 @@ module MMPlayer
32
27
  # @param [Proc] callback The callback to execute when the given MIDI note is received
33
28
  # @return [Hash]
34
29
  def add_note_callback(note, &callback)
35
- @config[:note][note] = callback
36
- @config[:note]
30
+ @message_handler.add_callback(:note, note, &callback)
37
31
  end
38
32
 
39
33
  # Add a callback for a given MIDI control change
@@ -41,8 +35,7 @@ module MMPlayer
41
35
  # @param [Proc] callback The callback to execute when the given MIDI control change is received
42
36
  # @return [Hash]
43
37
  def add_cc_callback(index, &callback)
44
- @config[:cc][index] = callback
45
- @config[:cc]
38
+ @message_handler.add_callback(:cc, index, &callback)
46
39
  end
47
40
 
48
41
  # Stop the MIDI listener
@@ -69,35 +62,20 @@ module MMPlayer
69
62
  true
70
63
  end
71
64
 
65
+ # Whether the player is subscribed to all channels
66
+ # @return [Boolean]
67
+ def omni?
68
+ @channel.nil?
69
+ end
70
+
72
71
  private
73
72
 
74
- # Populate the MIDI listener events
73
+ # Populate the MIDI listener callback
75
74
  def populate_listener
76
- # Channel messages
77
- listener_options = {}
78
- # omni by default
79
- listener_options[:channel] = @channel unless @channel.nil?
80
- @listener.on_message(listener_options.merge(:class => MIDIMessage::NoteOn)) do |event|
81
- message = event[:message]
82
- unless (callback = @config[:note][message.note] || @config[:note][message.name]).nil?
83
- callback.call(message.velocity)
84
- end
85
- end
86
- @listener.on_message(listener_options.merge(:class => MIDIMessage::ControlChange)) do |event|
87
- message = event[:message]
88
- unless (callback = @config[:cc][message.index] || @config[:cc][message.name]).nil?
89
- callback.call(message.value)
90
- end
91
- end
92
- # Short messages
93
- @listener.on_message(:class => MIDIMessage::SystemRealtime) do |event|
75
+ @listener.on_message do |event|
94
76
  message = event[:message]
95
- name = message.name.downcase.to_sym
96
- unless (callback = @config[:system][name]).nil?
97
- callback.call
98
- end
77
+ @message_handler.process(@channel, message)
99
78
  end
100
- true
101
79
  end
102
80
 
103
81
  end
@@ -6,9 +6,9 @@ module MMPlayer
6
6
  # @param [Hash] options
7
7
  # @option options [String] :flags MPlayer command-line flags to use on startup
8
8
  def initialize(options = {})
9
- @mplayer_messages = []
10
9
  @flags = "-fixed-vo -idle"
11
10
  @flags += " #{options[:flags]}" unless options[:flags].nil?
11
+ @messenger = Messenger.new
12
12
  end
13
13
 
14
14
  # Play a media file
@@ -51,7 +51,7 @@ module MMPlayer
51
51
  if @player.nil? && MPlayer::Slave.method_defined?(method)
52
52
  # warn
53
53
  else
54
- send_mplayer_message { @player.send(method, *args, &block) }
54
+ @messenger.send_message { @player.send(method, *args, &block) }
55
55
  end
56
56
  end
57
57
 
@@ -59,7 +59,7 @@ module MMPlayer
59
59
  # @return [Boolean]
60
60
  def mplayer_respond_to?(method, include_private = false)
61
61
  (@player.nil? && MPlayer::Slave.method_defined?(method)) ||
62
- @player.respond_to?(method)
62
+ @player.respond_to?(method)
63
63
  end
64
64
 
65
65
  # Cause MPlayer to exit
@@ -72,32 +72,6 @@ module MMPlayer
72
72
 
73
73
  private
74
74
 
75
- # Sweep for leftover/hanging message threads
76
- def sweep_messages
77
- if @mplayer_messages.empty?
78
- false
79
- else
80
- sleep(0.01)
81
- @mplayer_messages.each(&:kill)
82
- true
83
- end
84
- end
85
-
86
- # Send mplayer a message async
87
- def send_mplayer_message(&block)
88
- sweep_messages
89
- thread = Thread.new do
90
- begin
91
- yield
92
- rescue Exception => exception
93
- Thread.main.raise(exception)
94
- end
95
- end
96
- thread.abort_on_exception = true
97
- @mplayer_messages << thread
98
- thread
99
- end
100
-
101
75
  # Get progress percentage from the MPlayer report
102
76
  def get_percentage(report)
103
77
  percent = (report[:position] / report[:length]) * 100
@@ -107,7 +81,7 @@ module MMPlayer
107
81
  # Poll MPlayer for progress information
108
82
  def poll_mplayer_progress
109
83
  time = nil
110
- send_mplayer_message do
84
+ @messenger.send_message do
111
85
  time = {
112
86
  :length => get_mplayer_float("time_length"),
113
87
  :position => get_mplayer_float("time_pos")
@@ -125,7 +99,7 @@ module MMPlayer
125
99
  # @param [String] file The media file to invoke MPlayer with
126
100
  # @return [MPlayer::Slave]
127
101
  def ensure_player(file)
128
- if @player.nil?
102
+ if @player.nil? && @player_thread.nil?
129
103
  @player_thread = Thread.new do
130
104
  begin
131
105
  @player = MPlayer::Slave.new(file, :options => @flags)
@@ -137,6 +111,57 @@ module MMPlayer
137
111
  end
138
112
  end
139
113
 
114
+ # Handle sending MPlayer messages
115
+ class Messenger
116
+
117
+ FREQUENCY_LIMIT = 0.1 # Throttle messages to 1 per this number seconds
118
+
119
+ def initialize
120
+ @messages = []
121
+ end
122
+
123
+ # Send mplayer a message asynch
124
+ # @return [Hash, nil]
125
+ def send_message(&block)
126
+ timestamp = Time.now.to_f
127
+ if @messages.empty? || !throttle?(timestamp, @messages.last[:timestamp])
128
+ thread = Thread.new do
129
+ begin
130
+ yield
131
+ rescue Exception => exception
132
+ Thread.main.raise(exception)
133
+ end
134
+ end
135
+ thread.abort_on_exception = true
136
+ record_message(thread, timestamp)
137
+ end
138
+ end
139
+
140
+ private
141
+
142
+ # Should adding a message be throttled for the given timestamp?
143
+ # @param [Float] timestamp
144
+ # @param [Float] last_timestamp
145
+ # @return [Boolean]
146
+ def throttle?(timestamp, last_timestamp)
147
+ timestamp - last_timestamp <= FREQUENCY_LIMIT
148
+ end
149
+
150
+ # Record that a message has been sent
151
+ # @param [Thread] thread
152
+ # @param [Float] timestamp
153
+ # @return [Hash]
154
+ def record_message(thread, timestamp)
155
+ message = {
156
+ :thread => thread,
157
+ :timestamp => timestamp
158
+ }
159
+ @messages << message
160
+ message
161
+ end
162
+
163
+ end
164
+
140
165
  end
141
166
 
142
167
  end
@@ -22,7 +22,7 @@ class MMPlayer::ContextTest < Minitest::Test
22
22
  context "#start" do
23
23
 
24
24
  setup do
25
- @context.midi.listener.expects(:on_message).times(3)
25
+ @context.midi.listener.expects(:on_message).once
26
26
  @context.midi.listener.expects(:start).once
27
27
  end
28
28
 
@@ -33,7 +33,7 @@ class MMPlayer::ContextTest < Minitest::Test
33
33
 
34
34
  should "activate player" do
35
35
  assert @context.start(:background => true)
36
- @context.stop
36
+ assert @context.stop
37
37
  end
38
38
 
39
39
  end
@@ -41,7 +41,7 @@ class MMPlayer::ContextTest < Minitest::Test
41
41
  context "#stop" do
42
42
 
43
43
  setup do
44
- @context.midi.listener.expects(:on_message).times(3)
44
+ @context.midi.listener.expects(:on_message).once
45
45
  @context.midi.listener.expects(:start).once
46
46
  @context.midi.listener.expects(:stop).once
47
47
  @context.player.expects(:quit).once
@@ -55,7 +55,7 @@ class MMPlayer::ContextTest < Minitest::Test
55
55
  end
56
56
 
57
57
  should "stop player" do
58
- @context.stop
58
+ assert @context.stop
59
59
  end
60
60
 
61
61
  end
@@ -0,0 +1,254 @@
1
+ require "helper"
2
+
3
+ class MMPlayer::MessageHandlerTest < Minitest::Test
4
+
5
+ context "MessageHandler" do
6
+
7
+ setup do
8
+ @handler = MMPlayer::MessageHandler.new
9
+ end
10
+
11
+ context "#note_message" do
12
+
13
+ setup do
14
+ @message = MIDIMessage::NoteOn.new(0, 10, 100)
15
+ end
16
+
17
+ context "callback exists" do
18
+
19
+ setup do
20
+ @var = nil
21
+ @callback = proc { |vel| @var = vel }
22
+ @handler.add_callback(:note, @message.note, &@callback)
23
+ @callback.expects(:call).once
24
+ end
25
+
26
+ teardown do
27
+ @callback.unstub(:call)
28
+ end
29
+
30
+ should "call callback" do
31
+ assert @handler.send(:note_message, @message)
32
+ end
33
+
34
+ end
35
+
36
+ context "callback doesn't exist" do
37
+
38
+ should "do nothing" do
39
+ refute @handler.send(:note_message, @message)
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ context "#cc_message" do
47
+
48
+ setup do
49
+ @message = MIDIMessage::ControlChange.new(0, 8, 100)
50
+ end
51
+
52
+ context "callback exists" do
53
+
54
+ setup do
55
+ @var = nil
56
+ @callback = proc { |vel| @var = vel }
57
+ @handler.add_callback(:cc, @message.index, &@callback)
58
+ @callback.expects(:call).once
59
+ end
60
+
61
+ teardown do
62
+ @callback.unstub(:call)
63
+ end
64
+
65
+ should "call callback" do
66
+ assert @handler.send(:cc_message, @message)
67
+ end
68
+
69
+ end
70
+
71
+ context "callback doesn't exist" do
72
+
73
+ should "do nothing" do
74
+ refute @handler.send(:cc_message, @message)
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
81
+ context "#system_message" do
82
+
83
+ setup do
84
+ @message = MIDIMessage::SystemRealtime.new(0x8) # clock
85
+ end
86
+
87
+ context "callback exists" do
88
+
89
+ setup do
90
+ @var = nil
91
+ @callback = proc { |vel| @var = vel }
92
+ @handler.add_callback(:system, :clock, &@callback)
93
+ @callback.expects(:call).once
94
+ end
95
+
96
+ teardown do
97
+ @callback.unstub(:call)
98
+ end
99
+
100
+ should "call callback" do
101
+ assert @handler.send(:system_message, @message)
102
+ end
103
+
104
+ end
105
+
106
+ context "callback doesn't exist" do
107
+
108
+ should "do nothing" do
109
+ refute @handler.send(:system_message, @message)
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ context "#channel_message" do
117
+
118
+ context "omni" do
119
+
120
+ setup do
121
+ @channel = nil
122
+ end
123
+
124
+ context "control change" do
125
+
126
+ setup do
127
+ @message = MIDIMessage::ControlChange.new(0, 8, 100)
128
+ @handler.expects(:cc_message).once.with(@message).returns(true)
129
+ end
130
+
131
+ teardown do
132
+ @handler.unstub(:cc_message)
133
+ end
134
+
135
+ should "handle control change" do
136
+ assert @handler.send(:channel_message, @channel, @message)
137
+ end
138
+
139
+ end
140
+
141
+ context "note" do
142
+
143
+ setup do
144
+ @message = MIDIMessage::NoteOn.new(0, 10, 100)
145
+ @handler.expects(:note_message).once.with(@message).returns(true)
146
+ end
147
+
148
+ teardown do
149
+ @handler.unstub(:note_message)
150
+ end
151
+
152
+ should "handle note" do
153
+ assert @handler.send(:channel_message, @channel, @message)
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+
160
+ context "with channel" do
161
+
162
+ setup do
163
+ @channel = 5
164
+ end
165
+
166
+ context "control change" do
167
+
168
+ setup do
169
+ @message = MIDIMessage::ControlChange.new(@channel, 8, 100)
170
+ end
171
+
172
+ context "matching channel" do
173
+
174
+ setup do
175
+ @handler.expects(:cc_message).once.with(@message).returns(true)
176
+ end
177
+
178
+ teardown do
179
+ @handler.unstub(:cc_message)
180
+ end
181
+
182
+ should "handle control change" do
183
+ assert @handler.send(:channel_message, @channel, @message)
184
+ end
185
+
186
+ end
187
+
188
+ context "non matching channel" do
189
+
190
+ setup do
191
+ @handler.expects(:cc_message).never
192
+ @other_message = MIDIMessage::ControlChange.new(@channel + 1, 8, 100)
193
+ end
194
+
195
+ teardown do
196
+ @handler.unstub(:cc_message)
197
+ end
198
+
199
+ should "do nothing" do
200
+ refute @handler.send(:channel_message, @channel, @other_message)
201
+ end
202
+
203
+ end
204
+
205
+ end
206
+
207
+ context "note" do
208
+
209
+ setup do
210
+ @message = MIDIMessage::NoteOn.new(@channel, 10, 100)
211
+ end
212
+
213
+ context "matching channel" do
214
+
215
+ setup do
216
+ @handler.expects(:note_message).once.with(@message).returns(true)
217
+ end
218
+
219
+ teardown do
220
+ @handler.unstub(:note_message)
221
+ end
222
+
223
+ should "call callback" do
224
+ assert @handler.send(:channel_message, @channel, @message)
225
+ end
226
+
227
+ end
228
+
229
+ context "non matching channel" do
230
+
231
+ setup do
232
+ @handler.expects(:note_message).never
233
+ @other_message = MIDIMessage::ControlChange.new(@channel + 1, 8, 100)
234
+ end
235
+
236
+ teardown do
237
+ @handler.unstub(:note_message)
238
+ end
239
+
240
+ should "not call callback" do
241
+ refute @handler.send(:channel_message, @channel, @other_message)
242
+ end
243
+
244
+ end
245
+
246
+ end
247
+
248
+ end
249
+
250
+ end
251
+
252
+ end
253
+
254
+ end
@@ -12,7 +12,7 @@ class MMPlayer::MIDITest < Minitest::Test
12
12
  context "#start" do
13
13
 
14
14
  setup do
15
- @midi.listener.expects(:on_message).times(3)
15
+ @midi.listener.expects(:on_message).once
16
16
  @midi.listener.expects(:start).once
17
17
  end
18
18
 
@@ -35,8 +35,8 @@ class MMPlayer::MIDITest < Minitest::Test
35
35
  end
36
36
 
37
37
  should "store callback" do
38
- refute_nil @midi.config[:note][10]
39
- assert_equal Proc, @midi.config[:note][10].class
38
+ refute_nil @midi.message_handler.callback[:note][10]
39
+ assert_equal Proc, @midi.message_handler.callback[:note][10].class
40
40
  end
41
41
 
42
42
  end
@@ -49,8 +49,8 @@ class MMPlayer::MIDITest < Minitest::Test
49
49
  end
50
50
 
51
51
  should "store callback" do
52
- refute_nil @midi.config[:system][:start]
53
- assert_equal Proc, @midi.config[:system][:start].class
52
+ refute_nil @midi.message_handler.callback[:system][:start]
53
+ assert_equal Proc, @midi.message_handler.callback[:system][:start].class
54
54
  end
55
55
 
56
56
  end
@@ -63,8 +63,8 @@ class MMPlayer::MIDITest < Minitest::Test
63
63
  end
64
64
 
65
65
  should "store callback" do
66
- refute_nil @midi.config[:cc][2]
67
- assert_equal Proc, @midi.config[:cc][2].class
66
+ refute_nil @midi.message_handler.callback[:cc][2]
67
+ assert_equal Proc, @midi.message_handler.callback[:cc][2].class
68
68
  end
69
69
 
70
70
  end
@@ -96,11 +96,13 @@ class MMPlayer::MIDITest < Minitest::Test
96
96
  should "change channel" do
97
97
  assert_equal 3, @midi.channel = 3
98
98
  assert_equal 3, @midi.channel
99
+ refute @midi.omni?
99
100
  end
100
101
 
101
102
  should "set channel nil" do
102
103
  assert_equal nil, @midi.channel = nil
103
104
  assert_nil @midi.channel
105
+ assert @midi.omni?
104
106
  end
105
107
  end
106
108
 
@@ -109,17 +111,19 @@ class MMPlayer::MIDITest < Minitest::Test
109
111
  setup do
110
112
  @listener.stubs(:running?).returns(true)
111
113
  @listener.expects(:clear).once
112
- @listener.expects(:on_message).times(3)
114
+ @listener.expects(:on_message).once
113
115
  end
114
116
 
115
117
  should "change channel" do
116
118
  assert_equal 3, @midi.channel = 3
117
119
  assert_equal 3, @midi.channel
120
+ refute @midi.omni?
118
121
  end
119
122
 
120
123
  should "set channel nil" do
121
124
  assert_equal nil, @midi.channel = nil
122
125
  assert_nil @midi.channel
126
+ assert @midi.omni?
123
127
  end
124
128
 
125
129
  end
@@ -127,4 +131,5 @@ class MMPlayer::MIDITest < Minitest::Test
127
131
  end
128
132
 
129
133
  end
134
+
130
135
  end
@@ -120,6 +120,24 @@ class MMPlayer::PlayerTest < Minitest::Test
120
120
 
121
121
  end
122
122
 
123
+ context "Messenger" do
124
+
125
+ context "#throttle?" do
126
+
127
+ setup do
128
+ @messenger = MMPlayer::Player::Messenger.new
129
+ @limit = MMPlayer::Player::Messenger::FREQUENCY_LIMIT
130
+ end
131
+
132
+ should "respect message frequency" do
133
+ assert @messenger.send(:throttle?, 1234, 1234 - @limit / 2)
134
+ refute @messenger.send(:throttle?, 1234, 1234 - @limit * 2)
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
123
141
  end
124
142
 
125
143
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmplayer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Russo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-24 00:00:00.000000000 Z
11
+ date: 2015-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -204,6 +204,7 @@ files:
204
204
  - lib/mmplayer/helper/numbers.rb
205
205
  - lib/mmplayer/instructions/midi.rb
206
206
  - lib/mmplayer/instructions/player.rb
207
+ - lib/mmplayer/message_handler.rb
207
208
  - lib/mmplayer/midi.rb
208
209
  - lib/mmplayer/player.rb
209
210
  - test/context_test.rb
@@ -211,6 +212,7 @@ files:
211
212
  - test/helper/numbers_test.rb
212
213
  - test/instructions/midi_test.rb
213
214
  - test/instructions/player_test.rb
215
+ - test/message_handler_test.rb
214
216
  - test/midi_test.rb
215
217
  - test/player_test.rb
216
218
  homepage: http://github.com/arirusso/mmplayer