lib/surface_master/orbit/device.rb in surface_master-0.5.0 vs lib/surface_master/orbit/device.rb in surface_master-0.5.1
- old
+ new
@@ -5,75 +5,97 @@
include MIDICodes
def initialize(opts = nil)
@name = "Numark ORBIT"
super(opts)
- reset!
+ init!
end
- def reset!
+ def reset!; end
+
+ def init!
# Hack to get around apparent portmidi message truncation.
return
# Skip Sysex begin, vendor header, command code, aaaaand sysex end --
# this will let us compare command vs. response payloads to determine
# if the state of the device is what we want. Of course, sometimes it
# lies, but we can't do much about that.
- # expected_state = MAPPINGS[6..-2]
+ # expected_state = MAPPINGS[1..-1]
# sysex!(MAPPINGS)
# sleep 0.1
# sysex!(READ_STATE)
- # current_state = nil
- # started_at = Time.now.to_f
- # attempts = 1
+ # current_state = []
+ # started_at = Time.now.to_f
+ # attempts = 1
+ # state = :looking_for_start
# loop do
- # # TODO: It appears that accessing `buffer` is HIGHLY unsafe! We may
- # # TODO: be OK if everyone's waiting on us to come back from this
- # # TODO: method before they begin clamoring for input, but that's just
- # # TODO: a guess right now.
- # if @input.buffer.length == 0
+ # raw = @input.read
+ # unless raw
# elapsed = Time.now.to_f - started_at
# if elapsed > 4.0
- # logger.warn { "Timeout fetching state of Numark Orbit!" }
+ # logger.error { "Timeout fetching state of Numark Orbit!" }
# break
# elsif elapsed > (1.0 * attempts)
- # logger.warn { "Asking for current state of Numark Orbit again!" }
- # attempts += 1
- # @output.puts(READ_STATE)
+ # logger.error { "Asking for current state of Numark Orbit again!" }
+ # attempts += 1
+ # current_state = []
+ # state = :looking_for_start
+ # sysex!(READ_STATE)
# next
# end
# sleep 0.01
# next
# end
- # raw = @input.gets
- # current_state = raw.find { |ii| ii[:data][0] == 0xF0 }
- # break unless current_state.nil?
- # end
- # return unless current_state
-
- # current_state = current_state[:data][6..-2].dup
- # logger.debug { "Got state info from Numark Orbit!" }
- # if expected_state != current_state
- # logger.error { "UH OH! Numark Orbit state didn't match what we sent!" }
- # logger.error { "Expected: #{expected_state.inspect}" }
- # logger.error { "Got: #{current_state.inspect}" }
- # else
- # logger.debug { "Your Numark Orbit should be in the right state now." }
+ # case state
+ # when :looking_for_start
+ # idx = raw.find_index { |ii| ii[:message][0] == 0xF0 }
+ # if idx
+ # state = :looking_for_end
+ # raw = raw[idx..-1]
+ # current_state += raw.map { |ii| ii[:message] }.flatten
+ # end
+ # when :looking_for_end
+ # idx = raw.find_index { |ii| ii[:message][0] == 0xF7 }
+ # if idx
+ # # TODO: Now what?
+ # current_state = current_state[6..-1]
+ # if expected_state != current_state
+ # logger.error { "UH OH! Numark Orbit state didn't match what we sent!" }
+ # logger.error { "Expected: #{format_msg(expected_state)}" }
+ # logger.error { "Got: #{format_msg(current_state)}" }
+ # else
+ # logger.debug { "Your Numark Orbit should be in the right state now." }
+ # return
+ # end
+ # else
+ # idx = -1
+ # end
+ # raw = raw[0..idx]
+ # current_state += raw.map { |ii| ii[:message] }.flatten
+ # end
# end
+
+ # logger.error { "Didn't get state from Numark Orbit!" }
end
def read
super
.map { |input| decode_input(input) }
.compact
end
protected
- MAPPINGS = [0x03, 0x01, 0x70,
+ MAPPINGS = [0x03, # Command byte.
+ # Some aspect of internal state I don't understand...
+ 0x01, 0x70,
+
+ # Pad mappings. (Channel, Note, Color) for banks 1-4.
+ # These are addressed left-to-right, top-to-bottom.
0x00, 0x00, 0x00,
0x00, 0x04, 0x00,
0x00, 0x08, 0x00,
0x00, 0x0C, 0x00,
0x00, 0x01, 0x00,
@@ -86,10 +108,11 @@
0x00, 0x0E, 0x00,
0x00, 0x03, 0x00,
0x00, 0x07, 0x00,
0x00, 0x0B, 0x00,
0x00, 0x0F, 0x00,
+
0x01, 0x00, 0x00,
0x01, 0x04, 0x00,
0x01, 0x08, 0x00,
0x01, 0x0C, 0x00,
0x01, 0x01, 0x00,
@@ -102,26 +125,28 @@
0x01, 0x0E, 0x00,
0x01, 0x03, 0x00,
0x01, 0x07, 0x00,
0x01, 0x0B, 0x00,
0x01, 0x0F, 0x00,
+
0x02, 0x00, 0x00,
0x02, 0x04, 0x00,
0x02, 0x08, 0x00,
0x02, 0x0C, 0x00,
0x02, 0x01, 0x00,
0x02, 0x05, 0x00,
0x02, 0x09, 0x00,
- 0x02, 0x0D, 0x00,
+ 0x02, 0x0D, 0x00, # After here is where shit goes sideways...
0x02, 0x02, 0x00,
0x02, 0x06, 0x00,
0x02, 0x0A, 0x00,
0x02, 0x0E, 0x00,
0x02, 0x03, 0x00,
0x02, 0x07, 0x00,
0x02, 0x0B, 0x00,
0x02, 0x0F, 0x00,
+
0x03, 0x00, 0x00,
0x03, 0x04, 0x00,
0x03, 0x08, 0x00,
0x03, 0x0C, 0x00,
0x03, 0x01, 0x00,
@@ -135,25 +160,45 @@
0x03, 0x03, 0x00,
0x03, 0x07, 0x00,
0x03, 0x0B, 0x00,
0x03, 0x0F, 0x00,
- 0x00, 0x00, 0x01,
- 0x00, 0x02, 0x00,
- 0x03, 0x00, 0x00,
- 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x03,
- 0x01, 0x00, 0x02,
- 0x01, 0x02, 0x02,
- 0x02, 0x03, 0x02,
- 0x00, 0x03, 0x01,
- 0x03, 0x02, 0x03,
- 0x03, 0x03, 0x0C,
- 0x00, 0x0D, 0x00,
- 0x0C, 0x00, 0x0D,
- 0x00, 0x0C, 0x00,
- 0x0D, 0x00, 0x0C,
- 0x00, 0x0D, 0x00]
+ # VKnob buttons, I think. Ordered by bank, then vknob.
+ # High nybble of first byte is 0x0 for abslute, 0x1 for
+ # relative. Low nybble is channel. Second byte is CC.
+ 0x00, 0x00,
+ 0x01, 0x00,
+ 0x02, 0x00,
+ 0x03, 0x00,
+
+ 0x00, 0x01,
+ 0x01, 0x01,
+ 0x02, 0x01,
+ 0x03, 0x01,
+
+ 0x00, 0x02,
+ 0x01, 0x02,
+ 0x02, 0x02,
+ 0x03, 0x02,
+
+ 0x00, 0x03,
+ 0x01, 0x03,
+ 0x02, 0x03,
+ 0x03, 0x03,
+
+ # Shoulder buttons. Channel/CC pairs for left, then right
+ # through each of the four banks.
+ 0x0C, 0x00,
+ 0x0D, 0x00,
+
+ 0x0C, 0x00,
+ 0x0D, 0x00,
+
+ 0x0C, 0x00,
+ 0x0D, 0x00,
+
+ 0x0C, 0x00,
+ 0x0D, 0x00]
READ_STATE = [0x01, 0x00, 0x00]
def sysex_prefix; @sysex_prefix ||= super + [0x00, 0x01, 0x3F, 0x2B]; end
def decode_shoulder(decoded, note, _velocity)