Class: SurfaceMaster::Launchpad::Device

Inherits:
Device
  • Object
show all
Includes:
MIDICodes
Defined in:
lib/surface_master/launchpad/device.rb

Overview

Low-level interface to Novation Launchpad Mark 2 control surface.

Constant Summary collapse

CODE_NOTE_TO_TYPE =

TODO: Rename scenes to match Mk2

Hash.new { |*_| :grid }
.merge([Status::ON, Scene::SCENE1]     => :scene1,
       [Status::ON, Scene::SCENE2]     => :scene2,
       [Status::ON, Scene::SCENE3]     => :scene3,
       [Status::ON, Scene::SCENE4]     => :scene4,
       [Status::ON, Scene::SCENE5]     => :scene5,
       [Status::ON, Scene::SCENE6]     => :scene6,
       [Status::ON, Scene::SCENE7]     => :scene7,
       [Status::ON, Scene::SCENE8]     => :scene8,
       [Status::CC, Control::UP]       => :up,
       [Status::CC, Control::DOWN]     => :down,
       [Status::CC, Control::LEFT]     => :left,
       [Status::CC, Control::RIGHT]    => :right,
       [Status::CC, Control::SESSION]  => :session,
       [Status::CC, Control::USER1]    => :user1,
       [Status::CC, Control::USER2]    => :user2,
       [Status::CC, Control::MIXER]    => :mixer)
.freeze
TYPE_TO_NOTE =
{ up:      Control::UP,
down:    Control::DOWN,
left:    Control::LEFT,
right:   Control::RIGHT,
session: Control::SESSION,
user1:   Control::USER1,
user2:   Control::USER2,
mixer:   Control::MIXER,
scene1:  Scene::SCENE1, # Volume
scene2:  Scene::SCENE2, # Pan
scene3:  Scene::SCENE3, # Send A
scene4:  Scene::SCENE4, # Send B
scene5:  Scene::SCENE5, # Stop
scene6:  Scene::SCENE6, # Mute
scene7:  Scene::SCENE7, # Solo
scene8:  Scene::SCENE8 }.freeze

Instance Method Summary collapse

Methods inherited from Device

#close, #closed?, #input_enabled?, #output_enabled?, #reset!

Methods included from SurfaceMaster::Logging

#logger, #logger=

Constructor Details

#initialize(opts = nil) ⇒ Device

Record Arm



43
44
45
46
47
# File 'lib/surface_master/launchpad/device.rb', line 43

def initialize(opts = nil)
  @name = "Launchpad MK2"
  super(opts)
  reset! if output_enabled?
end

Instance Method Details

#change(opts = nil) ⇒ Object

TODO: Support more of the LaunchPad Mark 2’s functionality.



57
58
59
60
61
62
63
64
# File 'lib/surface_master/launchpad/device.rb', line 57

def change(opts = nil)
  fail NoOutputAllowedError unless output_enabled?

  opts ||= {}
  command, payload = color_payload(opts)
  sysex!(command, payload[:led], payload[:color])
  nil
end

#changes(values) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/surface_master/launchpad/device.rb', line 66

def changes(values)
  fail NoOutputAllowedError unless output_enabled?

  organize_commands(values).each do |command, payloads|
    # The documented batch size for RGB LED updates is 80.  The docs lie, at least on my
    # current firmware version -- anything above 62 crashes the device hard.
    while (slice = payloads.shift(62)).length > 0
      messages = slice.map { |payload| [payload[:led], payload[:color]] }
      sysex!(command, *messages)
    end
  end
  nil
end

#readObject



80
81
82
83
84
85
86
87
88
89
# File 'lib/surface_master/launchpad/device.rb', line 80

def read
  fail NoInputAllowedError unless input_enabled?
  super.collect do |input|
    note                  = input.delete(:note)
    input[:type]          = CODE_NOTE_TO_TYPE[[input.delete(:code), note]] || :grid
    input[:x], input[:y]  = decode_grid_coord(note) if input[:type] == :grid
    input.delete(:velocity)
    input
  end
end

#resetObject



49
50
51
52
53
# File 'lib/surface_master/launchpad/device.rb', line 49

def reset
  # TODO: Suss out what this should be for the Mark 2.
  layout!(0x00)
  output!(Status::CC, Status::NIL, Status::NIL)
end