lib/surface_master/orbit/device.rb in surface_master-0.2.1 vs lib/surface_master/orbit/device.rb in surface_master-0.4.0
- old
+ new
@@ -9,151 +9,199 @@
super(opts)
reset!
end
def reset!
- # TODO: This... doesn't appear to work. At all.
- if (result = sysex!(*MAPPINGS)) != 0
- fail "Expected success (0) setting mappings, got: #{result}"
+ # 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]
+ sysex!(MAPPINGS)
+ sleep 0.1
+ sysex!(READ_STATE)
+ current_state = nil
+ started_at = Time.now.to_f
+ attempts = 1
+ 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
+ elapsed = Time.now.to_f - started_at
+ if elapsed > 4.0
+ logger.warn { "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)
+ 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
- sysex!(0x01, 0x00, 0x00)
+
+ 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." }
+ end
end
def read
super
.map { |input| decode_input(input) }
.compact
end
protected
- MAPPINGS = [0x03, 0x01, 0x70,
- 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x00,
- 0x00, 0x08, 0x00,
- 0x00, 0x0C, 0x00,
- 0x00, 0x01, 0x00,
- 0x00, 0x05, 0x00,
- 0x00, 0x09, 0x00,
- 0x00, 0x0D, 0x00,
- 0x00, 0x02, 0x00,
- 0x00, 0x06, 0x00,
- 0x00, 0x0A, 0x00,
- 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,
- 0x01, 0x05, 0x00,
- 0x01, 0x09, 0x00,
- 0x01, 0x0D, 0x00,
- 0x01, 0x02, 0x00,
- 0x01, 0x06, 0x00,
- 0x01, 0x0A, 0x00,
- 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, 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,
- 0x03, 0x05, 0x00,
- 0x03, 0x09, 0x00,
- 0x03, 0x0D, 0x00,
- 0x03, 0x02, 0x00,
- 0x03, 0x06, 0x00,
- 0x03, 0x0A, 0x00,
- 0x03, 0x0E, 0x00,
- 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]
+ MAPPINGS = [0x03, 0x01, 0x70,
+ 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00,
+ 0x00, 0x08, 0x00,
+ 0x00, 0x0C, 0x00,
+ 0x00, 0x01, 0x00,
+ 0x00, 0x05, 0x00,
+ 0x00, 0x09, 0x00,
+ 0x00, 0x0D, 0x00,
+ 0x00, 0x02, 0x00,
+ 0x00, 0x06, 0x00,
+ 0x00, 0x0A, 0x00,
+ 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,
+ 0x01, 0x05, 0x00,
+ 0x01, 0x09, 0x00,
+ 0x01, 0x0D, 0x00,
+ 0x01, 0x02, 0x00,
+ 0x01, 0x06, 0x00,
+ 0x01, 0x0A, 0x00,
+ 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, 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,
+ 0x03, 0x05, 0x00,
+ 0x03, 0x09, 0x00,
+ 0x03, 0x0D, 0x00,
+ 0x03, 0x02, 0x00,
+ 0x03, 0x06, 0x00,
+ 0x03, 0x0A, 0x00,
+ 0x03, 0x0E, 0x00,
+ 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]
+ READ_STATE = [0x01, 0x00, 0x00]
+
def sysex_prefix; @sysex_prefix ||= super + [0x00, 0x01, 0x3F, 0x2B]; end
def decode_shoulder(decoded, note, _velocity)
- decoded[:control].merge!(SurfaceMaster::Orbit::Device::SHOULDERS[note])
+ decoded[:control] = decoded[:control].merge(SurfaceMaster::Orbit::Device::SHOULDERS[note])
decoded
end
def decode_pad(decoded, note, _velocity)
- decoded[:control][:button] = note
+ decoded[:control] = decoded[:control].merge(button: note + 1)
decoded
end
def decode_knob(decoded, note, velocity)
- decoded[:control][:bank] = note + 1
- decoded[:value] = velocity
+ decoded[:control] = decoded[:control].merge(bank: note + 1)
+ decoded[:value] = velocity
decoded
end
def decode_control(decoded, note, velocity)
- tmp = SurfaceMaster::Orbit::Device::SELECTORS[note]
- tmp[:index] = velocity
- decoded[:control].merge!(tmp)
+ decoded = decoded.merge(SurfaceMaster::Orbit::Device::SELECTORS[note])
+ decoded[:control] = { button: velocity }
decoded
end
+ def decode_accelerometer(decoded, _note, velocity)
+ decoded[:value] = velocity
+ decoded
+ end
+
def enrich_decoded_message(decoded, note, velocity, timestamp)
case decoded[:type]
- when :shoulder then decoded = decode_shoulder(decoded, note, velocity)
- when :pad then decoded = decode_pad(decoded, note, velocity)
- when :knob then decoded = decode_knob(decoded, note, velocity)
- when :control then decoded = decode_control(decoded, note, velocity)
+ when :shoulder then decoded = decode_shoulder(decoded, note, velocity)
+ when :pad then decoded = decode_pad(decoded, note, velocity)
+ when :vknob then decoded = decode_knob(decoded, note, velocity)
+ when :accelerometer then decoded = decode_accelerometer(decoded, note, velocity)
+ else decoded = decode_control(decoded, note, velocity)
end
decoded[:timestamp] = timestamp
decoded
end
def decode_input(input)
-# puts [input[:code].to_hex, input[:note].to_hex, input[:velocity].to_hex].join(" ")
note = input[:note]
velocity = input[:velocity]
code_high = input[:code] & 0xF0
code_low = input[:code] & 0x0F
raw = SurfaceMaster::Orbit::Device::CONTROLS[code_high]
raw = raw[code_low] if raw
- raw = enrich_decoded_message(raw, note, velocity, input[:timestamp]) if raw
+ raw = enrich_decoded_message(raw.dup, note, velocity, input[:timestamp]) if raw
raw
end
end
end
end