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