surface_master 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +107 -0
- data/.travis.yml +2 -3
- data/CHANGELOG.md +16 -0
- data/Gemfile +5 -1
- data/Rakefile +73 -5
- data/debug_tools/decode.rb +1 -1
- data/examples/launchpad_testbed.rb +67 -28
- data/examples/monitor.rb +23 -11
- data/examples/orbit_testbed.rb +1 -42
- data/lib/surface_master/device.rb +40 -39
- data/lib/surface_master/interaction.rb +81 -55
- data/lib/surface_master/launchpad/device.rb +70 -58
- data/lib/surface_master/launchpad/errors.rb +8 -9
- data/lib/surface_master/launchpad/interaction.rb +24 -42
- data/lib/surface_master/orbit/device.rb +85 -85
- data/lib/surface_master/orbit/interaction.rb +1 -0
- data/lib/surface_master/orbit/midi_codes.rb +3 -1
- data/lib/surface_master/version.rb +2 -1
- data/lib/{control_center.rb → surface_master.rb} +0 -0
- data/surface_master.gemspec +7 -5
- data/test/helper.rb +16 -17
- data/test/test_device.rb +167 -355
- data/test/test_interaction.rb +177 -188
- metadata +5 -3
data/test/test_interaction.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "timeout"
|
3
3
|
|
4
4
|
class BreakError < StandardError; end
|
5
5
|
|
6
|
-
describe Launchpad::Interaction do
|
7
|
-
|
6
|
+
describe SurfaceMaster::Launchpad::Interaction do
|
8
7
|
# returns true/false whether the operation ended or the timeout was hit
|
9
8
|
def timeout(timeout = 0.02, &block)
|
10
9
|
Timeout.timeout(timeout, &block)
|
@@ -18,323 +17,320 @@ describe Launchpad::Interaction do
|
|
18
17
|
interaction.respond_to(type, :up, opts)
|
19
18
|
end
|
20
19
|
|
21
|
-
|
22
20
|
def press_all(interaction)
|
23
21
|
%w(up down left right session user1 user2 mixer).each do |type|
|
24
22
|
press(interaction, type.to_sym)
|
25
23
|
end
|
26
24
|
8.times do |y|
|
27
25
|
8.times do |x|
|
28
|
-
press(interaction, :grid, :
|
26
|
+
press(interaction, :grid, x: x, y: y)
|
29
27
|
end
|
30
28
|
press(interaction, :"scene#{y + 1}")
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
32
|
describe '#initialize' do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
interaction = Launchpad::Interaction.new
|
33
|
+
it "creates device if not given" do
|
34
|
+
device = SurfaceMaster::Launchpad::Device.new
|
35
|
+
SurfaceMaster::Launchpad::Device.expects(:new)
|
36
|
+
.with(input: true, output: true, logger: nil)
|
37
|
+
.returns(device)
|
38
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new
|
42
39
|
assert_same device, interaction.device
|
43
40
|
end
|
44
41
|
|
45
|
-
it
|
46
|
-
device = Launchpad::Device.new
|
47
|
-
Launchpad::Device.expects(:new)
|
48
|
-
with(:
|
49
|
-
returns(device)
|
50
|
-
interaction = Launchpad::Interaction.new(:
|
42
|
+
it "creates device with given device_name" do
|
43
|
+
device = SurfaceMaster::Launchpad::Device.new
|
44
|
+
SurfaceMaster::Launchpad::Device.expects(:new)
|
45
|
+
.with(device_name: "device", input: true, output: true, logger: nil)
|
46
|
+
.returns(device)
|
47
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(device_name: "device")
|
51
48
|
assert_same device, interaction.device
|
52
49
|
end
|
53
50
|
|
54
|
-
it
|
55
|
-
device = Launchpad::Device.new
|
56
|
-
Launchpad::Device.expects(:new)
|
57
|
-
with(:
|
58
|
-
returns(device)
|
59
|
-
interaction = Launchpad::Interaction.new(:
|
51
|
+
it "creates device with given input_device_id" do
|
52
|
+
device = SurfaceMaster::Launchpad::Device.new
|
53
|
+
SurfaceMaster::Launchpad::Device.expects(:new)
|
54
|
+
.with(input_device_id: "in", input: true, output: true, logger: nil)
|
55
|
+
.returns(device)
|
56
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(input_device_id: "in")
|
60
57
|
assert_same device, interaction.device
|
61
58
|
end
|
62
59
|
|
63
|
-
it
|
64
|
-
device = Launchpad::Device.new
|
65
|
-
Launchpad::Device.expects(:new)
|
66
|
-
with(:
|
67
|
-
returns(device)
|
68
|
-
interaction = Launchpad::Interaction.new(:
|
60
|
+
it "creates device with given output_device_id" do
|
61
|
+
device = SurfaceMaster::Launchpad::Device.new
|
62
|
+
SurfaceMaster::Launchpad::Device.expects(:new)
|
63
|
+
.with(output_device_id: "out", input: true, output: true, logger: nil)
|
64
|
+
.returns(device)
|
65
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(output_device_id: "out")
|
69
66
|
assert_same device, interaction.device
|
70
67
|
end
|
71
68
|
|
72
|
-
it
|
73
|
-
device = Launchpad::Device.new
|
74
|
-
Launchpad::Device
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
it "creates device with given input_device_id/output_device_id" do
|
70
|
+
device = SurfaceMaster::Launchpad::Device.new
|
71
|
+
SurfaceMaster::Launchpad::Device
|
72
|
+
.expects(:new)
|
73
|
+
.with(input_device_id: "in",
|
74
|
+
output_device_id: "out",
|
75
|
+
input: true,
|
76
|
+
output: true,
|
77
|
+
logger: nil)
|
78
|
+
.returns(device)
|
79
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(input_device_id: "in",
|
80
|
+
output_device_id: "out")
|
78
81
|
assert_same device, interaction.device
|
79
82
|
end
|
80
83
|
|
81
|
-
it
|
82
|
-
device = Launchpad::Device.new
|
83
|
-
interaction = Launchpad::Interaction.new(:
|
84
|
+
it "initializes device if given" do
|
85
|
+
device = SurfaceMaster::Launchpad::Device.new
|
86
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(device: device)
|
84
87
|
assert_same device, interaction.device
|
85
88
|
end
|
86
89
|
|
87
|
-
it
|
90
|
+
it "stores the logger given" do
|
88
91
|
logger = Logger.new(nil)
|
89
|
-
interaction = Launchpad::Interaction.new(:
|
92
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(logger: logger)
|
90
93
|
assert_same logger, interaction.logger
|
91
94
|
assert_same logger, interaction.device.logger
|
92
95
|
end
|
93
96
|
|
94
97
|
it 'doesn\'t activate the interaction' do
|
95
|
-
assert !Launchpad::Interaction.new.active
|
98
|
+
assert !SurfaceMaster::Launchpad::Interaction.new.active
|
96
99
|
end
|
97
|
-
|
98
100
|
end
|
99
101
|
|
100
102
|
describe '#logger=' do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
interaction = Launchpad::Interaction.new
|
105
|
-
interaction.logger = logger
|
103
|
+
it "stores the logger and passes it to the device as well" do
|
104
|
+
logger = Logger.new(nil)
|
105
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new(logger: logger)
|
106
106
|
assert_same logger, interaction.logger
|
107
107
|
assert_same logger, interaction.device.logger
|
108
108
|
end
|
109
|
-
|
110
109
|
end
|
111
110
|
|
112
111
|
describe '#close' do
|
113
|
-
|
114
|
-
|
115
|
-
interaction = Launchpad::Interaction.new
|
112
|
+
it "stops the interaction" do
|
113
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new
|
116
114
|
interaction.expects(:stop)
|
117
115
|
interaction.close
|
118
116
|
end
|
119
117
|
|
120
|
-
it
|
121
|
-
interaction = Launchpad::Interaction.new
|
118
|
+
it "closes the device" do
|
119
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new
|
122
120
|
interaction.device.expects(:close)
|
123
121
|
interaction.close
|
124
122
|
end
|
125
|
-
|
126
123
|
end
|
127
124
|
|
128
125
|
describe '#closed?' do
|
129
|
-
|
130
|
-
|
131
|
-
interaction = Launchpad::Interaction.new
|
126
|
+
it "returns false on a newly created interaction, but true after closing" do
|
127
|
+
interaction = SurfaceMaster::Launchpad::Interaction.new
|
132
128
|
assert !interaction.closed?
|
133
129
|
interaction.close
|
134
130
|
assert interaction.closed?
|
135
131
|
end
|
136
|
-
|
137
132
|
end
|
138
133
|
|
139
134
|
describe '#start' do
|
140
|
-
|
141
135
|
before do
|
142
|
-
@interaction = Launchpad::Interaction.new
|
136
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new
|
143
137
|
end
|
144
138
|
|
145
139
|
after do
|
146
140
|
mocha_teardown # so that expectations on Thread.join don't fail in here
|
147
141
|
begin
|
148
142
|
@interaction.close
|
143
|
+
# rubocop:disable Lint/HandleExceptions
|
149
144
|
rescue
|
145
|
+
# rubocop:enable Lint/HandleExceptions
|
150
146
|
# ignore, should be handled in tests, this is just to close all the spawned threads
|
151
147
|
end
|
152
148
|
end
|
153
149
|
|
154
|
-
it
|
150
|
+
it "sets active to true in blocking mode" do
|
155
151
|
refute @interaction.active
|
156
152
|
erg = timeout { @interaction.start }
|
157
|
-
refute erg,
|
153
|
+
refute erg, "there was no timeout"
|
158
154
|
assert @interaction.active
|
159
155
|
end
|
160
156
|
|
161
|
-
it
|
157
|
+
it "sets active to true in detached mode" do
|
162
158
|
refute @interaction.active
|
163
|
-
@interaction.start(:
|
159
|
+
@interaction.start(detached: true)
|
164
160
|
assert @interaction.active
|
165
161
|
end
|
166
162
|
|
167
|
-
it
|
163
|
+
it "blocks in blocking mode" do
|
168
164
|
erg = timeout { @interaction.start }
|
169
|
-
refute erg,
|
165
|
+
refute erg, "there was no timeout"
|
170
166
|
end
|
171
167
|
|
172
|
-
it
|
173
|
-
erg = timeout { @interaction.start(:
|
174
|
-
assert erg,
|
168
|
+
it "returns immediately in detached mode" do
|
169
|
+
erg = timeout { @interaction.start(detached: true) }
|
170
|
+
assert erg, "there was a timeout"
|
175
171
|
end
|
176
172
|
|
177
|
-
it
|
178
|
-
@interaction.device.stubs(:
|
179
|
-
assert_raises
|
173
|
+
it "raises CommunicationError when Portmidi::DeviceError occurs" do
|
174
|
+
@interaction.device.stubs(:read).raises(Portmidi::DeviceError.new(0))
|
175
|
+
assert_raises SurfaceMaster::CommunicationError do
|
180
176
|
@interaction.start
|
181
177
|
end
|
182
178
|
end
|
183
179
|
|
184
|
-
describe
|
185
|
-
|
180
|
+
describe "action handling" do
|
186
181
|
before do
|
187
182
|
@interaction.response_to(:mixer, :down) { @mixer_down = true }
|
188
|
-
@interaction.response_to(:mixer, :up) do |i,
|
183
|
+
@interaction.response_to(:mixer, :up) do |i, _a|
|
189
184
|
sleep 0.001 # sleep to make "sure" :mixer :down has been processed
|
190
185
|
i.stop
|
191
186
|
end
|
192
|
-
@interaction.device.expects(:
|
193
|
-
at_least_once
|
194
|
-
returns([
|
195
|
-
{
|
196
|
-
:
|
197
|
-
:
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
:timestamp => 0,
|
202
|
-
:state => :up,
|
203
|
-
:type => :mixer
|
204
|
-
}
|
187
|
+
@interaction.device.expects(:read)
|
188
|
+
.at_least_once
|
189
|
+
.returns([
|
190
|
+
{ timestamp: 0,
|
191
|
+
state: :down,
|
192
|
+
type: :mixer },
|
193
|
+
{ timestamp: 0,
|
194
|
+
state: :up,
|
195
|
+
type: :mixer },
|
205
196
|
])
|
206
197
|
end
|
207
198
|
|
208
|
-
it
|
199
|
+
it "calls respond_to_action with actions from respond_to_action in blocking mode" do
|
209
200
|
erg = timeout(0.5) { @interaction.start }
|
210
201
|
assert erg, 'the actions weren\'t called'
|
211
202
|
assert @mixer_down, 'the mixer button wasn\'t pressed'
|
212
203
|
end
|
213
204
|
|
214
|
-
it
|
215
|
-
@interaction.start(:
|
216
|
-
erg = timeout(0.5) { while @interaction.active
|
217
|
-
assert erg,
|
205
|
+
it "calls respond_to_action with actions from respond_to_action in detached mode" do
|
206
|
+
@interaction.start(detached: true)
|
207
|
+
erg = timeout(0.5) { sleep 0.01 while @interaction.active }
|
208
|
+
assert erg, "there was a timeout"
|
218
209
|
assert @mixer_down, 'the mixer button wasn\'t pressed'
|
219
210
|
end
|
220
|
-
|
221
211
|
end
|
222
212
|
|
223
|
-
describe
|
213
|
+
describe "latency" do
|
214
|
+
# TODO: This seems like a REALLY janky way to handle these tests...
|
215
|
+
|
216
|
+
# TODO: Also, at best the flow of which-code-creates-which-instance is
|
217
|
+
# TODO: confusing here, and at worst it's doing something unexpected
|
218
|
+
# TODO: that only works by accident.
|
224
219
|
|
225
220
|
before do
|
226
221
|
@device = @interaction.device
|
227
222
|
@times = []
|
228
223
|
@device.instance_variable_set("@test_interaction_latency_times", @times)
|
229
|
-
def @device.
|
224
|
+
def @device.read
|
230
225
|
@test_interaction_latency_times << Time.now.to_f
|
231
226
|
[]
|
232
227
|
end
|
233
228
|
end
|
234
229
|
|
235
|
-
it
|
230
|
+
it "sleeps with default latency of 0.001s when none given" do
|
231
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new(device: @device)
|
236
232
|
timeout { @interaction.start }
|
237
233
|
assert @times.size > 1
|
238
|
-
@times.each_cons(2) do |a,b|
|
234
|
+
@times.each_cons(2) do |a, b|
|
235
|
+
# TODO: This.. this is meaningless. WTF.
|
239
236
|
assert_in_delta 0.001, b - a, 0.01
|
240
237
|
end
|
241
238
|
end
|
242
239
|
|
243
|
-
it
|
244
|
-
@interaction = Launchpad::Interaction.new(:
|
240
|
+
it "sleeps with given latency" do
|
241
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new(latency: 0.5, device: @device)
|
245
242
|
timeout(0.55) { @interaction.start }
|
246
243
|
assert @times.size > 1
|
247
|
-
@times.each_cons(2) do |a,b|
|
244
|
+
@times.each_cons(2) do |a, b|
|
248
245
|
assert_in_delta 0.5, b - a, 0.01
|
249
246
|
end
|
250
247
|
end
|
251
248
|
|
252
|
-
it
|
253
|
-
@interaction = Launchpad::Interaction.new(:
|
249
|
+
it "sleeps with absolute value of given negative latency" do
|
250
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new(latency: -0.1, device: @device)
|
254
251
|
timeout(0.15) { @interaction.start }
|
255
252
|
assert @times.size > 1
|
256
|
-
@times.each_cons(2) do |a,b|
|
257
|
-
assert_in_delta 0.1, b - a, 0.
|
253
|
+
@times.each_cons(2) do |a, b|
|
254
|
+
assert_in_delta 0.1, b - a, 0.11
|
258
255
|
end
|
259
256
|
end
|
260
257
|
|
261
|
-
it
|
262
|
-
@interaction = Launchpad::Interaction.new(:
|
263
|
-
timeout(0.
|
258
|
+
it "does not sleep when latency is 0" do
|
259
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new(latency: 0, device: @device)
|
260
|
+
timeout(0.01) { @interaction.start }
|
264
261
|
assert @times.size > 1
|
265
|
-
@
|
266
|
-
|
262
|
+
@interaction.stop
|
263
|
+
@times.each_cons(2) do |a, b|
|
264
|
+
assert_in_delta 0, b - a, 0.01
|
267
265
|
end
|
268
266
|
end
|
269
|
-
|
270
267
|
end
|
271
268
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
269
|
+
# TODO: This semantic doesn't appear to be working, and begs the question of whether
|
270
|
+
# TODO: that semantics is DESIRABLE.
|
271
|
+
# it 'resets the device after the loop' do
|
272
|
+
# @interaction.device.expects(:reset)
|
273
|
+
# @interaction.start(detached: true)
|
274
|
+
# @interaction.stop
|
275
|
+
# end
|
277
276
|
|
278
|
-
it
|
277
|
+
it "raises NoInputAllowedError on closed interaction" do
|
279
278
|
@interaction.close
|
280
|
-
assert_raises
|
279
|
+
assert_raises SurfaceMaster::NoInputAllowedError do
|
281
280
|
@interaction.start
|
282
281
|
end
|
283
282
|
end
|
284
|
-
|
285
283
|
end
|
286
284
|
|
287
285
|
describe '#stop' do
|
288
|
-
|
289
286
|
before do
|
290
|
-
@interaction = Launchpad::Interaction.new
|
287
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new
|
291
288
|
end
|
292
289
|
|
293
|
-
it
|
290
|
+
it "sets active to false in blocking mode" do
|
294
291
|
erg = timeout { @interaction.start }
|
295
|
-
refute erg,
|
292
|
+
refute erg, "there was no timeout"
|
296
293
|
assert @interaction.active
|
297
294
|
@interaction.stop
|
298
295
|
assert !@interaction.active
|
299
296
|
end
|
300
297
|
|
301
|
-
it
|
302
|
-
@interaction.start(:
|
298
|
+
it "sets active to false in detached mode" do
|
299
|
+
@interaction.start(detached: true)
|
303
300
|
assert @interaction.active
|
304
301
|
@interaction.stop
|
305
302
|
assert !@interaction.active
|
306
303
|
end
|
307
304
|
|
308
|
-
it
|
305
|
+
it "is callable anytime" do
|
309
306
|
@interaction.stop
|
310
|
-
@interaction.start(:
|
307
|
+
@interaction.start(detached: true)
|
311
308
|
@interaction.stop
|
312
309
|
@interaction.stop
|
313
310
|
end
|
314
311
|
|
315
|
-
# this is kinda greybox tested, since I couldn't come up with another way to test
|
316
|
-
|
317
|
-
|
312
|
+
# this is kinda greybox tested, since I couldn't come up with another way to test thread
|
313
|
+
# handling [thomas, 2010-01-24]
|
314
|
+
it "raises pending exceptions in detached mode" do
|
315
|
+
t = Thread.new { fail BreakError }
|
318
316
|
Thread.expects(:new).returns(t)
|
319
|
-
@interaction.start(:
|
317
|
+
@interaction.start(detached: true)
|
320
318
|
assert_raises BreakError do
|
321
319
|
@interaction.stop
|
322
320
|
end
|
323
321
|
end
|
324
|
-
|
325
322
|
end
|
326
323
|
|
327
324
|
describe '#response_to/#no_response_to/#respond_to' do
|
328
|
-
|
329
325
|
before do
|
330
|
-
@interaction = Launchpad::Interaction.new
|
326
|
+
@interaction = SurfaceMaster::Launchpad::Interaction.new
|
331
327
|
end
|
332
328
|
|
333
|
-
it
|
334
|
-
@interaction.response_to(:mixer, :down) {|
|
335
|
-
@interaction.response_to(:all, :down) {|
|
336
|
-
@interaction.response_to(:all, :up) {|
|
337
|
-
@interaction.response_to(:grid, :down) {|
|
329
|
+
it "calls all responses that match, and not others" do
|
330
|
+
@interaction.response_to(:mixer, :down) { |_i, _a| @mixer_down = true }
|
331
|
+
@interaction.response_to(:all, :down) { |_i, _a| @all_down = true }
|
332
|
+
@interaction.response_to(:all, :up) { |_i, _a| @all_up = true }
|
333
|
+
@interaction.response_to(:grid, :down) { |_i, _a| @grid_down = true }
|
338
334
|
@interaction.respond_to(:mixer, :down)
|
339
335
|
assert @mixer_down
|
340
336
|
assert @all_down
|
@@ -342,10 +338,10 @@ describe Launchpad::Interaction do
|
|
342
338
|
assert !@grid_down
|
343
339
|
end
|
344
340
|
|
345
|
-
it
|
346
|
-
@interaction.response_to(:mixer, :down) {|
|
347
|
-
@interaction.response_to(:mixer, :up) {|
|
348
|
-
@interaction.response_to(:all, :both) {|
|
341
|
+
it "does not call responses when they are deregistered" do
|
342
|
+
@interaction.response_to(:mixer, :down) { |_i, _a| @mixer_down = true }
|
343
|
+
@interaction.response_to(:mixer, :up) { |_i, _a| @mixer_up = true }
|
344
|
+
@interaction.response_to(:all, :both) { |_i, a| @all_down = a[:state] == :down }
|
349
345
|
@interaction.no_response_to(:mixer, :down)
|
350
346
|
@interaction.respond_to(:mixer, :down)
|
351
347
|
assert !@mixer_down
|
@@ -357,8 +353,8 @@ describe Launchpad::Interaction do
|
|
357
353
|
assert !@all_down
|
358
354
|
end
|
359
355
|
|
360
|
-
it
|
361
|
-
@interaction.response_to(:mixer, :both) {|
|
356
|
+
it "does not call responses registered for both when removing for one of both states" do
|
357
|
+
@interaction.response_to(:mixer, :both) { |_i, _a| @mixer = true }
|
362
358
|
@interaction.no_response_to(:mixer, :down)
|
363
359
|
@interaction.respond_to(:mixer, :down)
|
364
360
|
assert !@mixer
|
@@ -366,9 +362,9 @@ describe Launchpad::Interaction do
|
|
366
362
|
assert @mixer
|
367
363
|
end
|
368
364
|
|
369
|
-
it
|
370
|
-
@interaction.response_to(:mixer, :both) {|
|
371
|
-
@interaction.response_to(:mixer, :down, :
|
365
|
+
it "removes other responses when adding a new exclusive response" do
|
366
|
+
@interaction.response_to(:mixer, :both) { |_i, _a| @mixer = true }
|
367
|
+
@interaction.response_to(:mixer, :down, exclusive: true) { |_i, _a| @exclusive_mixer = true }
|
372
368
|
@interaction.respond_to(:mixer, :down)
|
373
369
|
assert !@mixer
|
374
370
|
assert @exclusive_mixer
|
@@ -377,80 +373,73 @@ describe Launchpad::Interaction do
|
|
377
373
|
assert @exclusive_mixer
|
378
374
|
end
|
379
375
|
|
380
|
-
it
|
376
|
+
it "allows for multiple types" do
|
381
377
|
@downs = []
|
382
|
-
@interaction.response_to([:up, :down], :down) {|
|
378
|
+
@interaction.response_to([:up, :down], :down) { |_i, a| @downs << a[:type] }
|
383
379
|
@interaction.respond_to(:up, :down)
|
384
380
|
@interaction.respond_to(:down, :down)
|
385
381
|
@interaction.respond_to(:up, :down)
|
386
382
|
assert_equal [:up, :down, :up], @downs
|
387
383
|
end
|
388
384
|
|
389
|
-
describe
|
390
|
-
|
385
|
+
describe "allows to bind to specific grid buttons" do
|
391
386
|
before do
|
392
387
|
@downs = []
|
393
|
-
@action =
|
388
|
+
@action = ->(_i, a) { @downs << [a[:x], a[:y]] }
|
394
389
|
end
|
395
390
|
|
396
|
-
it
|
397
|
-
@interaction.response_to(:grid, :down, :
|
391
|
+
it "one specific grid button" do
|
392
|
+
@interaction.response_to(:grid, :down, x: 4, y: 2, &@action)
|
398
393
|
press_all @interaction
|
399
394
|
assert_equal [[4, 2]], @downs
|
400
395
|
end
|
401
396
|
|
402
|
-
it
|
403
|
-
@interaction.response_to(:grid, :down, :
|
397
|
+
it "a complete row of grid buttons" do
|
398
|
+
@interaction.response_to(:grid, :down, y: 2, &@action)
|
404
399
|
press_all @interaction
|
405
400
|
assert_equal [[0, 2], [1, 2], [2, 2], [3, 2], [4, 2], [5, 2], [6, 2], [7, 2]], @downs
|
406
401
|
end
|
407
402
|
|
408
|
-
it
|
409
|
-
@interaction.response_to(:grid, :down, :
|
403
|
+
it "a complete column of grid buttons" do
|
404
|
+
@interaction.response_to(:grid, :down, x: 3, &@action)
|
410
405
|
press_all @interaction
|
411
406
|
assert_equal [[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7]], @downs
|
412
407
|
end
|
413
408
|
|
414
|
-
it
|
415
|
-
@interaction.response_to(:grid, :down, :
|
409
|
+
it "a complex range of grid buttons" do
|
410
|
+
@interaction.response_to(:grid, :down, x: [1, [2]], y: [1, 3..5], &@action)
|
416
411
|
press_all @interaction
|
417
412
|
assert_equal [[1, 1], [2, 1], [1, 3], [2, 3], [1, 4], [2, 4], [1, 5], [2, 5]], @downs
|
418
413
|
end
|
419
414
|
|
420
|
-
it
|
421
|
-
@interaction.response_to(:all, :down) {|
|
422
|
-
@interaction.response_to(:grid, :down) {|
|
423
|
-
@interaction.response_to(:grid, :down, :
|
424
|
-
@interaction.response_to(:grid, :down, :
|
425
|
-
@interaction.response_to(:grid, :down, :
|
426
|
-
press @interaction, :grid, :
|
415
|
+
it "a specific grid buttons, a column, a row, all grid buttons and all buttons" do
|
416
|
+
@interaction.response_to(:all, :down) { |_i, a| @downs << [a[:x], a[:y], :all] }
|
417
|
+
@interaction.response_to(:grid, :down) { |_i, a| @downs << [a[:x], a[:y], :grid] }
|
418
|
+
@interaction.response_to(:grid, :down, x: 0) { |_i, a| @downs << [a[:x], a[:y], :col] }
|
419
|
+
@interaction.response_to(:grid, :down, y: 0) { |_i, a| @downs << [a[:x], a[:y], :row] }
|
420
|
+
@interaction.response_to(:grid, :down, x: 0, y: 0, &@action)
|
421
|
+
press @interaction, :grid, x: 0, y: 0
|
427
422
|
assert_equal [[0, 0], [0, 0, :col], [0, 0, :row], [0, 0, :grid], [0, 0, :all]], @downs
|
428
423
|
end
|
429
|
-
|
430
424
|
end
|
431
|
-
|
432
425
|
end
|
433
426
|
|
434
|
-
describe
|
435
|
-
|
436
|
-
it 'does not raise an exception or write an error to the logger when calling stop within a response in attached mode' do
|
427
|
+
describe "regression tests" do
|
428
|
+
it "doesn't kvetch when calling stop in response in attached mode" do
|
437
429
|
log = StringIO.new
|
438
430
|
logger = Logger.new(log)
|
439
431
|
logger.level = Logger::ERROR
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
at_least_once
|
444
|
-
returns([{
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
erg = timeout { i.start }
|
432
|
+
inter = SurfaceMaster::Launchpad::Interaction.new(logger: logger)
|
433
|
+
inter.response_to(:mixer, :down) { |i, _a| i.stop }
|
434
|
+
inter.device.expects(:read)
|
435
|
+
.at_least_once
|
436
|
+
.returns([{ timestamp: 0,
|
437
|
+
state: :down,
|
438
|
+
type: :mixer }])
|
439
|
+
# erg =
|
440
|
+
timeout { inter.start }
|
450
441
|
# assert erg, 'the actions weren\'t called'
|
451
|
-
assert_equal
|
442
|
+
assert_equal "", log.string
|
452
443
|
end
|
453
|
-
|
454
444
|
end
|
455
|
-
|
456
445
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surface_master
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Frisby
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: portmidi
|
@@ -47,7 +47,9 @@ extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
49
|
- ".gitignore"
|
50
|
+
- ".rubocop.yml"
|
50
51
|
- ".travis.yml"
|
52
|
+
- CHANGELOG.md
|
51
53
|
- Gemfile
|
52
54
|
- LICENSE
|
53
55
|
- README.md
|
@@ -74,7 +76,7 @@ files:
|
|
74
76
|
- examples/launchpad_testbed.rb
|
75
77
|
- examples/monitor.rb
|
76
78
|
- examples/orbit_testbed.rb
|
77
|
-
- lib/
|
79
|
+
- lib/surface_master.rb
|
78
80
|
- lib/surface_master/device.rb
|
79
81
|
- lib/surface_master/errors.rb
|
80
82
|
- lib/surface_master/interaction.rb
|