surface_master 0.4.1 → 0.5.0

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: b3c8e66c72e0225a04e8fbe61bbffc2d477de6c6
4
- data.tar.gz: c3ac84410c8799b5b345c9692f99ccd91ec562a6
3
+ metadata.gz: 94debb23931c0d4acfc807e8c537442ebc4f34bf
4
+ data.tar.gz: bf26b6479e46056fd7ca580464cca8c2b9b98e80
5
5
  SHA512:
6
- metadata.gz: 03da9f7ecd866d2133fc46b57fa4ad295c46edbe93588c221ce73a8ca11d1d9a3e2de748872769fab960888219d2df3bac9c0e45ff245d864da1d2ced9e51a41
7
- data.tar.gz: fcf81c4609204ffdcc882c68c4187f0992ba7f3d9f2a65f2c134798b34557cc74d63550f6f818364e33c6d8bc4070e84dece0480e41bf0c2ece55dfa74210917
6
+ metadata.gz: af1db6281a6c2802bcdf177452788c047bbb59358db6d5695ce8b5020522d22859c7622d76444351bd394d9f565e76f58fa98cd1a3126f2448949b2794cd9621
7
+ data.tar.gz: d4ccfa6aed322a129725ba6600c643c398b121d34f1ab7e5e4937e2b67cf2f70193b0632eded87f0b017ef95a3e3f2b36d96db131d40ea7c18af79f8219bb50f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changes
2
2
 
3
+ ## v0.5.0
4
+
5
+ * Make all addressing for Numark Orbit be zero-based.
6
+ * Switch to grid addressing for Numark Orbit (backwards incompatible change!).
7
+
8
+
3
9
  ## v0.4.1
4
10
 
5
11
  * Add a simple driver for the TouchOSC Bridge.
@@ -7,17 +7,17 @@ require "surface_master"
7
7
 
8
8
  SurfaceMaster.init!
9
9
  interaction = SurfaceMaster::Orbit::Interaction.new
10
- interaction.response_to(:pad, :down) do |_inter, action|
10
+ interaction.response_to(:grid, :down) do |_inter, action|
11
11
  puts "PAD DOWN: #{action.inspect}"
12
12
  end
13
- interaction.response_to(:pad, :up) do |_inter, action|
13
+ interaction.response_to(:grid, :up) do |_inter, action|
14
14
  puts "PAD UP: #{action.inspect}"
15
15
  end
16
- interaction.response_to(:pad, :up, button: 1..4) do |_inter, action|
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(:pad, :up, button: 5..8, bank: 4, exclusive: true) do |_inter, action|
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: 4, vknob: 1) do |_inter, action|
33
- puts "KNOB 1, BANK 4 TURNED: #{action.inspect}"
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, offset: 0x03, use_read: true, read_delay: 0.1 },
30
- wired: { delay: 0.1, offset: 0x01, use_read: false, read_delay: 0 } }
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,
@@ -76,7 +76,7 @@ module SurfaceMaster
76
76
  protected
77
77
 
78
78
  def expand(list)
79
- list.map { |ll| ll.respond_to?(:to_a) ? ll.to_a : ll }.flatten
79
+ Array(list).map { |ll| ll.respond_to?(:to_a) ? ll.to_a : ll }.flatten
80
80
  end
81
81
 
82
82
  def guard_input_and_reset_at_end!(&block)
@@ -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
- # TODO: It appears that accessing `buffer` is HIGHLY unsafe! We may
27
- # TODO: be OK if everyone's waiting on us to come back from this
28
- # TODO: method before they begin clamoring for input, but that's just
29
- # TODO: a guess right now.
30
- if @input.buffer.length == 0
31
- elapsed = Time.now.to_f - started_at
32
- if elapsed > 4.0
33
- logger.warn { "Timeout fetching state of Numark Orbit!" }
34
- break
35
- elsif elapsed > (1.0 * attempts)
36
- logger.warn { "Asking for current state of Numark Orbit again!" }
37
- attempts += 1
38
- @output.puts(READ_STATE)
39
- next
40
- end
41
- sleep 0.01
42
- next
43
- end
44
- raw = @input.gets
45
- current_state = raw.find { |ii| ii[:data][0] == 0xF0 }
46
- break unless current_state.nil?
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
- logger.error { "UH OH! Numark Orbit state didn't match what we sent!" }
55
- logger.error { "Expected: #{expected_state.inspect}" }
56
- logger.error { "Got: #{current_state.inspect}" }
57
- else
58
- logger.debug { "Your Numark Orbit should be in the right state now." }
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 decode_pad(decoded, note, _velocity)
163
- decoded[:control] = decoded[:control].merge(button: note + 1)
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 + 1)
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 :pad then decoded = decode_pad(decoded, note, velocity)
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? ? [1..4] : [opts[:vknob]]
20
- banks = opts[:bank].nil? ? [1..4] : [opts[:bank]]
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? ? [1..4] : [opts[:button]]
31
+ buttons = opts[:button].nil? ? [0..3] : [opts[:button]]
25
32
 
26
33
  expand(buttons).map { |b| [:"#{type}-#{b}"] }
27
- when :pad
28
- banks = opts[:bank].nil? ? [1..4] : [opts[:bank]]
29
- buttons = opts[:button].nil? ? [1..16] : [opts[:button]]
30
-
31
- expand(buttons).product(expand(banks)).map { |p, b| :"#{type}-#{p}-#{b}" }
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: :pad, state: :down, control: { bank: 1 } },
10
- 0x01 => { type: :pad, state: :down, control: { bank: 2 } },
11
- 0x02 => { type: :pad, state: :down, control: { bank: 3 } },
12
- 0x03 => { type: :pad, state: :down, control: { bank: 4 } },
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: :pad, state: :up, control: { bank: 1 } },
15
- 0x01 => { type: :pad, state: :up, control: { bank: 2 } },
16
- 0x02 => { type: :pad, state: :up, control: { bank: 3 } },
17
- 0x03 => { type: :pad, state: :up, control: { bank: 4 } },
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: 1 } },
20
- 0x01 => { type: :vknob, state: :update, control: { vknob: 2 } },
21
- 0x02 => { type: :vknob, state: :update, control: { vknob: 3 } },
22
- 0x03 => { type: :vknob, state: :update, control: { vknob: 4 } },
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
@@ -1,4 +1,4 @@
1
1
  #
2
2
  module SurfaceMaster
3
- VERSION = "0.4.1"
3
+ VERSION = "0.5.0"
4
4
  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.1
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-13 00:00:00.000000000 Z
11
+ date: 2015-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: portmidi