surface_master 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/examples/orbit_interaction.rb +7 -7
- data/examples/orbit_playground.rb +2 -2
- data/lib/surface_master/interaction.rb +1 -1
- data/lib/surface_master/orbit/device.rb +49 -46
- data/lib/surface_master/orbit/interaction.rb +33 -8
- data/lib/surface_master/orbit/midi_codes.rb +12 -12
- data/lib/surface_master/touch_osc/device.rb +1 -6
- data/lib/surface_master/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94debb23931c0d4acfc807e8c537442ebc4f34bf
|
4
|
+
data.tar.gz: bf26b6479e46056fd7ca580464cca8c2b9b98e80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af1db6281a6c2802bcdf177452788c047bbb59358db6d5695ce8b5020522d22859c7622d76444351bd394d9f565e76f58fa98cd1a3126f2448949b2794cd9621
|
7
|
+
data.tar.gz: d4ccfa6aed322a129725ba6600c643c398b121d34f1ab7e5e4937e2b67cf2f70193b0632eded87f0b017ef95a3e3f2b36d96db131d40ea7c18af79f8219bb50f
|
data/CHANGELOG.md
CHANGED
@@ -7,17 +7,17 @@ require "surface_master"
|
|
7
7
|
|
8
8
|
SurfaceMaster.init!
|
9
9
|
interaction = SurfaceMaster::Orbit::Interaction.new
|
10
|
-
interaction.response_to(:
|
10
|
+
interaction.response_to(:grid, :down) do |_inter, action|
|
11
11
|
puts "PAD DOWN: #{action.inspect}"
|
12
12
|
end
|
13
|
-
interaction.response_to(:
|
13
|
+
interaction.response_to(:grid, :up) do |_inter, action|
|
14
14
|
puts "PAD UP: #{action.inspect}"
|
15
15
|
end
|
16
|
-
interaction.response_to(:
|
16
|
+
interaction.response_to(:grid, :up, x: 0) do |_inter, action|
|
17
17
|
puts "LEFT COLUMN PAD UP: #{action.inspect}"
|
18
18
|
end
|
19
|
-
interaction.response_to(:
|
20
|
-
puts "SECOND-FROM-LEFT COLUMN PAD UP: #{action.inspect}"
|
19
|
+
interaction.response_to(:grid, :up, x: 1, y: 0..3, bank: 3, exclusive: true) do |_inter, action|
|
20
|
+
puts "SECOND-FROM-LEFT COLUMN, LAST BANK, PAD UP: #{action.inspect}"
|
21
21
|
end
|
22
22
|
|
23
23
|
interaction.response_to(:vknob, :update) do |_inter, action|
|
@@ -29,8 +29,8 @@ end
|
|
29
29
|
interaction.response_to(:vknob, :update, bank: 2, exclusive: true) do |_inter, action|
|
30
30
|
puts "ANY KNOB, BANK 2 TURNED: #{action.inspect}"
|
31
31
|
end
|
32
|
-
interaction.response_to(:vknob, :update, bank:
|
33
|
-
puts "KNOB 1, BANK
|
32
|
+
interaction.response_to(:vknob, :update, bank: 1, vknob: 1) do |_inter, action|
|
33
|
+
puts "KNOB 1, BANK 1 TURNED: #{action.inspect}"
|
34
34
|
end
|
35
35
|
|
36
36
|
interaction.response_to(:accelerometer, :tilt) do |_inter, action|
|
@@ -26,8 +26,8 @@ device = SurfaceMaster::Orbit::Device.new
|
|
26
26
|
# TODO: Can we safely get input simultaneously?
|
27
27
|
MODE = :wired
|
28
28
|
|
29
|
-
CONFIGS = { wireless: { delay: 0.75,
|
30
|
-
wired: { delay: 0.1, offset: 0x01, use_read: false,
|
29
|
+
CONFIGS = { wireless: { delay: 0.75, offset: 0x03, use_read: true, read_delay: 0.1 },
|
30
|
+
wired: { delay: 0.1, offset: 0x01, use_read: false, read_delay: 0 } }
|
31
31
|
MAPPINGS = [0x03, 0x01, 0x70,
|
32
32
|
|
33
33
|
0x00, 0x00, 0x00,
|
@@ -11,52 +11,55 @@ module SurfaceMaster
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def reset!
|
14
|
+
# Hack to get around apparent portmidi message truncation.
|
15
|
+
return
|
16
|
+
|
14
17
|
# Skip Sysex begin, vendor header, command code, aaaaand sysex end --
|
15
18
|
# this will let us compare command vs. response payloads to determine
|
16
19
|
# if the state of the device is what we want. Of course, sometimes it
|
17
20
|
# lies, but we can't do much about that.
|
18
|
-
expected_state = MAPPINGS[6..-2]
|
19
|
-
sysex!(MAPPINGS)
|
20
|
-
sleep 0.1
|
21
|
-
sysex!(READ_STATE)
|
22
|
-
current_state = nil
|
23
|
-
started_at = Time.now.to_f
|
24
|
-
attempts = 1
|
25
|
-
loop do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
return unless current_state
|
50
|
-
|
51
|
-
current_state = current_state[:data][6..-2].dup
|
52
|
-
logger.debug { "Got state info from Numark Orbit!" }
|
53
|
-
if expected_state != current_state
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
|
59
|
-
end
|
21
|
+
# expected_state = MAPPINGS[6..-2]
|
22
|
+
# sysex!(MAPPINGS)
|
23
|
+
# sleep 0.1
|
24
|
+
# sysex!(READ_STATE)
|
25
|
+
# current_state = nil
|
26
|
+
# started_at = Time.now.to_f
|
27
|
+
# attempts = 1
|
28
|
+
# loop do
|
29
|
+
# # TODO: It appears that accessing `buffer` is HIGHLY unsafe! We may
|
30
|
+
# # TODO: be OK if everyone's waiting on us to come back from this
|
31
|
+
# # TODO: method before they begin clamoring for input, but that's just
|
32
|
+
# # TODO: a guess right now.
|
33
|
+
# if @input.buffer.length == 0
|
34
|
+
# elapsed = Time.now.to_f - started_at
|
35
|
+
# if elapsed > 4.0
|
36
|
+
# logger.warn { "Timeout fetching state of Numark Orbit!" }
|
37
|
+
# break
|
38
|
+
# elsif elapsed > (1.0 * attempts)
|
39
|
+
# logger.warn { "Asking for current state of Numark Orbit again!" }
|
40
|
+
# attempts += 1
|
41
|
+
# @output.puts(READ_STATE)
|
42
|
+
# next
|
43
|
+
# end
|
44
|
+
# sleep 0.01
|
45
|
+
# next
|
46
|
+
# end
|
47
|
+
# raw = @input.gets
|
48
|
+
# current_state = raw.find { |ii| ii[:data][0] == 0xF0 }
|
49
|
+
# break unless current_state.nil?
|
50
|
+
# end
|
51
|
+
|
52
|
+
# return unless current_state
|
53
|
+
|
54
|
+
# current_state = current_state[:data][6..-2].dup
|
55
|
+
# logger.debug { "Got state info from Numark Orbit!" }
|
56
|
+
# if expected_state != current_state
|
57
|
+
# logger.error { "UH OH! Numark Orbit state didn't match what we sent!" }
|
58
|
+
# logger.error { "Expected: #{expected_state.inspect}" }
|
59
|
+
# logger.error { "Got: #{current_state.inspect}" }
|
60
|
+
# else
|
61
|
+
# logger.debug { "Your Numark Orbit should be in the right state now." }
|
62
|
+
# end
|
60
63
|
end
|
61
64
|
|
62
65
|
def read
|
@@ -159,13 +162,13 @@ module SurfaceMaster
|
|
159
162
|
decoded
|
160
163
|
end
|
161
164
|
|
162
|
-
def
|
163
|
-
decoded[:control] = decoded[:control].merge(
|
165
|
+
def decode_grid(decoded, note, _velocity)
|
166
|
+
decoded[:control] = decoded[:control].merge(x: note / 4, y: note % 4)
|
164
167
|
decoded
|
165
168
|
end
|
166
169
|
|
167
170
|
def decode_knob(decoded, note, velocity)
|
168
|
-
decoded[:control] = decoded[:control].merge(bank: note
|
171
|
+
decoded[:control] = decoded[:control].merge(bank: note)
|
169
172
|
decoded[:value] = velocity
|
170
173
|
decoded
|
171
174
|
end
|
@@ -184,7 +187,7 @@ module SurfaceMaster
|
|
184
187
|
def enrich_decoded_message(decoded, note, velocity, timestamp)
|
185
188
|
case decoded[:type]
|
186
189
|
when :shoulder then decoded = decode_shoulder(decoded, note, velocity)
|
187
|
-
when :
|
190
|
+
when :grid then decoded = decode_grid(decoded, note, velocity)
|
188
191
|
when :vknob then decoded = decode_knob(decoded, note, velocity)
|
189
192
|
when :accelerometer then decoded = decode_accelerometer(decoded, note, velocity)
|
190
193
|
else decoded = decode_control(decoded, note, velocity)
|
@@ -9,6 +9,13 @@ module SurfaceMaster
|
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
+
def grid_range(range)
|
13
|
+
return [0..3] if range.nil?
|
14
|
+
Array(range).flatten.map do |pos|
|
15
|
+
pos.respond_to?(:to_a) ? pos.to_a : pos
|
16
|
+
end.flatten.uniq
|
17
|
+
end
|
18
|
+
|
12
19
|
def combined_types(type, opts = nil)
|
13
20
|
tmp = case type
|
14
21
|
when :shoulder
|
@@ -16,19 +23,20 @@ module SurfaceMaster
|
|
16
23
|
when :accelerometer
|
17
24
|
[:"#{type}-#{opts[:axis]}"]
|
18
25
|
when :vknob
|
19
|
-
knobs = opts[:vknob].nil? ? [
|
20
|
-
banks = opts[:bank].nil? ? [
|
26
|
+
knobs = opts[:vknob].nil? ? [0..3] : [opts[:vknob]]
|
27
|
+
banks = opts[:bank].nil? ? [0..3] : [opts[:bank]]
|
21
28
|
|
22
29
|
expand(knobs).product(expand(banks)).map { |k, b| :"#{type}-#{k}-#{b}" }
|
23
30
|
when :vknobs, :banks
|
24
|
-
buttons = opts[:button].nil? ? [
|
31
|
+
buttons = opts[:button].nil? ? [0..3] : [opts[:button]]
|
25
32
|
|
26
33
|
expand(buttons).map { |b| [:"#{type}-#{b}"] }
|
27
|
-
when :
|
28
|
-
banks
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
when :grid
|
35
|
+
banks = expand(opts[:bank] || [0..3])
|
36
|
+
x = expand(grid_range(opts[:x]))
|
37
|
+
y = expand(grid_range(opts[:y]))
|
38
|
+
# return [:grid] if x.nil? && y.nil? # whole grid
|
39
|
+
x.product(y).product(banks).map { |xx, (yy, b)| :"#{type}-#{xx}-#{yy}-#{b}" }
|
32
40
|
else
|
33
41
|
[type]
|
34
42
|
end
|
@@ -63,11 +71,28 @@ module SurfaceMaster
|
|
63
71
|
combined_types = combined_types(action[:type].to_sym, action[:control])
|
64
72
|
state = action[:state].to_sym
|
65
73
|
actions = []
|
74
|
+
if action[:type] == :grid
|
75
|
+
actions += mappings_for_grid_action(state, action[:control])
|
76
|
+
end
|
66
77
|
actions += combined_types.map { |ct| responses[ct][state] }
|
67
78
|
actions += responses[:all][state]
|
68
79
|
actions.flatten.compact
|
69
80
|
end
|
70
81
|
|
82
|
+
def mappings_for_grid_action(state, control)
|
83
|
+
x = control[:x]
|
84
|
+
y = control[:y]
|
85
|
+
bank = control[:bank]
|
86
|
+
actions = []
|
87
|
+
actions += responses[:"grid-#{x}-#{y}-#{bank}"][state]
|
88
|
+
actions += responses[:"grid-#{x}--#{bank}"][state]
|
89
|
+
actions += responses[:"grid--#{y}-#{bank}"][state]
|
90
|
+
actions += responses[:"grid-#{x}-#{y}-"][state]
|
91
|
+
actions += responses[:"grid-#{x}--"][state]
|
92
|
+
actions += responses[:"grid--#{y}-"][state]
|
93
|
+
actions
|
94
|
+
end
|
95
|
+
|
71
96
|
def expand_states(state)
|
72
97
|
case state
|
73
98
|
when :both then %i(down up)
|
@@ -6,20 +6,20 @@ module SurfaceMaster
|
|
6
6
|
module MIDICodes
|
7
7
|
# TODO: Use a lib to do a deep-freeze.
|
8
8
|
# rubocop:disable Metrics/LineLength
|
9
|
-
CONTROLS = { 0x90 => { 0x00 => { type: :
|
10
|
-
0x01 => { type: :
|
11
|
-
0x02 => { type: :
|
12
|
-
0x03 => { type: :
|
9
|
+
CONTROLS = { 0x90 => { 0x00 => { type: :grid, state: :down, control: { bank: 0 } },
|
10
|
+
0x01 => { type: :grid, state: :down, control: { bank: 1 } },
|
11
|
+
0x02 => { type: :grid, state: :down, control: { bank: 2 } },
|
12
|
+
0x03 => { type: :grid, state: :down, control: { bank: 3 } },
|
13
13
|
0x0F => { type: :shoulder, state: :down, control: {} } },
|
14
|
-
0x80 => { 0x00 => { type: :
|
15
|
-
0x01 => { type: :
|
16
|
-
0x02 => { type: :
|
17
|
-
0x03 => { type: :
|
14
|
+
0x80 => { 0x00 => { type: :grid, state: :up, control: { bank: 0 } },
|
15
|
+
0x01 => { type: :grid, state: :up, control: { bank: 1 } },
|
16
|
+
0x02 => { type: :grid, state: :up, control: { bank: 2 } },
|
17
|
+
0x03 => { type: :grid, state: :up, control: { bank: 3 } },
|
18
18
|
0x0F => { type: :shoulder, state: :up, control: {} } },
|
19
|
-
0xB0 => { 0x00 => { type: :vknob, state: :update, control: { vknob:
|
20
|
-
0x01 => { type: :vknob, state: :update, control: { vknob:
|
21
|
-
0x02 => { type: :vknob, state: :update, control: { vknob:
|
22
|
-
0x03 => { type: :vknob, state: :update, control: { vknob:
|
19
|
+
0xB0 => { 0x00 => { type: :vknob, state: :update, control: { vknob: 0 } },
|
20
|
+
0x01 => { type: :vknob, state: :update, control: { vknob: 1 } },
|
21
|
+
0x02 => { type: :vknob, state: :update, control: { vknob: 2 } },
|
22
|
+
0x03 => { type: :vknob, state: :update, control: { vknob: 3 } },
|
23
23
|
0x0C => { type: :accelerometer, state: :tilt, control: { axis: :x } },
|
24
24
|
0x0D => { type: :accelerometer, state: :tilt, control: { axis: :y } },
|
25
25
|
0x0F => { state: :down } } }.freeze
|
@@ -8,8 +8,7 @@ module SurfaceMaster
|
|
8
8
|
@mapper = mapper || proc { |input| input }
|
9
9
|
end
|
10
10
|
|
11
|
-
def reset
|
12
|
-
end
|
11
|
+
def reset!; end
|
13
12
|
|
14
13
|
def read
|
15
14
|
super
|
@@ -20,10 +19,6 @@ module SurfaceMaster
|
|
20
19
|
def write(messages)
|
21
20
|
@output.write(Array(messages))
|
22
21
|
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
# def sysex_prefix; @sysex_prefix ||= super + []; end
|
27
22
|
end
|
28
23
|
end
|
29
24
|
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.
|
4
|
+
version: 0.5.0
|
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-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: portmidi
|