Class: LaunchpadMk2::Interaction
- Inherits:
-
Object
- Object
- LaunchpadMk2::Interaction
- Includes:
- Logging
- Defined in:
- lib/launchpad_mk2/interaction.rb
Overview
This class provides advanced interaction features.
Example:
require 'launchpad_mk2'
interaction = Launchpad::Interaction.new
interaction.response_to(:grid, :down) do |interaction, action|
interaction.device.change(:grid, action.merge(:red => :high))
end
interaction.response_to(:mixer, :down) do |interaction, action|
interaction.stop
end
interaction.start
Instance Attribute Summary collapse
-
#active ⇒ Object
readonly
Returns whether the Launchpad::Interaction is active or not.
-
#device ⇒ Object
readonly
Returns the Launchpad::Device the Launchpad::Interaction acts on.
Instance Method Summary collapse
-
#close ⇒ Object
Closes the interaction’s device - nothing can be done with the interaction/device afterwards.
-
#closed? ⇒ Boolean
Determines whether this interaction’s device has been closed.
-
#initialize(opts = nil) ⇒ Interaction
constructor
Initializes the interaction.
-
#logger=(logger) ⇒ Object
Sets the logger to be used by the current instance and the device.
-
#no_response_to(types = nil, state = :both, opts = nil) ⇒ Object
Deregisters all responses to one or more actions.
-
#respond_to(type, state, opts = nil) ⇒ Object
Responds to an action by executing all matching responses, effectively simulating a button press/release.
-
#response_to(types = :all, state = :both, opts = nil, &block) ⇒ Object
Registers a response to one or more actions.
-
#start(opts = nil) ⇒ Object
Starts interacting with the launchpad.
-
#stop ⇒ Object
Stops interacting with the launchpad.
Methods included from Logging
Constructor Details
#initialize(opts = nil) ⇒ Interaction
Initializes the interaction.
Optional options hash:
:device
-
Launchpad::Device to act on, optional,
:input_device_id/:output_device_id
will be used if omitted :input_device_id
-
ID of the MIDI input device to use, optional,
:device_name
will be used if omitted :output_device_id
-
ID of the MIDI output device to use, optional,
:device_name
will be used if omitted :device_name
-
Name of the MIDI device to use, optional, defaults to “Launchpad”
:latency
-
delay (in s, fractions allowed) between MIDI pulls, optional, defaults to 0.001 (1ms)
:logger
- Logger
-
to be used by this interaction instance, can be changed afterwards
Errors raised:
- Launchpad::NoSuchDeviceError
-
when device with ID or name specified does not exist
- Launchpad::DeviceBusyError
-
when device with ID or name specified is busy
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/launchpad_mk2/interaction.rb', line 51 def initialize(opts = nil) @reader_thread = nil @device = nil opts ||= {} self.logger = opts[:logger] logger.debug "initializing Launchpad::Interaction##{object_id} with #{opts.inspect}" @device ||= opts[:device] @device ||= Device.new(opts.merge( :input => true, :output => true, :logger => opts[:logger] )) @latency = (opts[:latency] || 0.001).to_f.abs @active = false @action_threads = ThreadGroup.new end |
Instance Attribute Details
#active ⇒ Object (readonly)
Returns whether the Launchpad::Interaction is active or not.
29 30 31 |
# File 'lib/launchpad_mk2/interaction.rb', line 29 def active @active end |
#device ⇒ Object (readonly)
Returns the Launchpad::Device the Launchpad::Interaction acts on.
26 27 28 |
# File 'lib/launchpad_mk2/interaction.rb', line 26 def device @device end |
Instance Method Details
#close ⇒ Object
Closes the interaction’s device - nothing can be done with the interaction/device afterwards.
Errors raised:
- Launchpad::NoInputAllowedError
-
when input is not enabled on the interaction’s device
- Launchpad::CommunicationError
-
when anything unexpected happens while communicating with the
85 86 87 88 89 |
# File 'lib/launchpad_mk2/interaction.rb', line 85 def close logger.debug "closing Launchpad::Interaction##{object_id}" stop @device.close end |
#closed? ⇒ Boolean
Determines whether this interaction’s device has been closed.
92 93 94 |
# File 'lib/launchpad_mk2/interaction.rb', line 92 def closed? @device.closed? end |
#logger=(logger) ⇒ Object
Sets the logger to be used by the current instance and the device.
logger
-
the [Logger] instance
74 75 76 77 |
# File 'lib/launchpad_mk2/interaction.rb', line 74 def logger=(logger) @logger = logger @device.logger = logger if @device end |
#no_response_to(types = nil, state = :both, opts = nil) ⇒ Object
Deregisters all responses to one or more actions.
Parameters (see Launchpad for values):
types
-
one or an array of button types to respond to, additional value
:all
for actions on all buttons (but not meaning “all responses”), optional, defaults tonil
, meaning “all responses” state
-
button state to respond to, additional value
:both
Optional options hash:
:x
-
x coordinate(s), can contain arrays and ranges, when specified without y coordinate, it’s interpreted as a whole column
:y
-
y coordinate(s), can contain arrays and ranges, when specified without x coordinate, it’s interpreted as a whole row
225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/launchpad_mk2/interaction.rb', line 225 def no_response_to(types = nil, state = :both, opts = nil) logger.debug "removing response to #{types.inspect} for state #{state.inspect}" types = Array(types) Array(state == :both ? %w(down up) : state).each do |current_state| types.each do |type| combined_types(type, opts).each do |combined_type| responses[combined_type][current_state.to_sym].clear end end end nil end |
#respond_to(type, state, opts = nil) ⇒ Object
Responds to an action by executing all matching responses, effectively simulating a button press/release.
Parameters (see Launchpad for values):
type
-
type of the button to trigger
state
-
state of the button
Optional options hash (see Launchpad for values):
:x
-
x coordinate
:y
-
y coordinate
250 251 252 |
# File 'lib/launchpad_mk2/interaction.rb', line 250 def respond_to(type, state, opts = nil) respond_to_action((opts || {}).merge(:type => type, :state => state)) end |
#response_to(types = :all, state = :both, opts = nil, &block) ⇒ Object
Registers a response to one or more actions.
Parameters (see Launchpad for values):
types
-
one or an array of button types to respond to, additional value
:all
for all buttons state
-
button state to respond to, additional value
:both
Optional options hash:
:exclusive
-
true/false
, whether to deregister all other responses to the specified actions, optional, defaults tofalse
:x
-
x coordinate(s), can contain arrays and ranges, when specified without y coordinate, it’s interpreted as a whole column
:y
-
y coordinate(s), can contain arrays and ranges, when specified without x coordinate, it’s interpreted as a whole row
Takes a block which will be called when an action matching the parameters occurs.
Block parameters:
interaction
-
the interaction object that received the action
action
-
the action received from Launchpad::Device.read_pending_actions
193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/launchpad_mk2/interaction.rb', line 193 def response_to(types = :all, state = :both, opts = nil, &block) logger.debug "setting response to #{types.inspect} for state #{state.inspect} with #{opts.inspect}" types = Array(types) opts ||= {} no_response_to(types, state) if opts[:exclusive] == true Array(state == :both ? %w(down up) : state).each do |current_state| types.each do |type| combined_types(type, opts).each do |combined_type| responses[combined_type][current_state.to_sym] << block end end end nil end |
#start(opts = nil) ⇒ Object
Starts interacting with the launchpad. Resets the device when the interaction was properly stopped via stop or close.
Optional options hash:
:detached
-
true/false
, whether to detach the interaction, method is blocking whenfalse
, optional, defaults tofalse
Errors raised:
- Launchpad::NoInputAllowedError
-
when input is not enabled on the interaction’s device
- Launchpad::NoOutputAllowedError
-
when output is not enabled on the interaction’s device
- Launchpad::CommunicationError
-
when anything unexpected happens while communicating with the launchpad
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/launchpad_mk2/interaction.rb', line 110 def start(opts = nil) logger.debug "starting Launchpad::Interaction##{object_id}" opts = { :detached => false }.merge(opts || {}) @active = true @reader_thread ||= Thread.new do begin while @active do @device.read_pending_actions.each do |pending_action| action_thread = Thread.new(pending_action) do |action| respond_to_action(action) end @action_threads.add(action_thread) end sleep @latency# if @latency > 0.0 end rescue Portmidi::DeviceError => e logger.fatal "could not read from device, stopping to read actions" raise CommunicationError.new(e) rescue Exception => e logger.fatal "error causing action reading to stop: #{e.inspect}" raise e end end @reader_thread.join unless opts[:detached] end |
#stop ⇒ Object
Stops interacting with the launchpad.
Errors raised:
- Launchpad::NoInputAllowedError
-
when input is not enabled on the interaction’s device
- Launchpad::CommunicationError
-
when anything unexpected happens while communicating with the
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/launchpad_mk2/interaction.rb', line 147 def stop logger.debug "stopping Launchpad::Interaction##{object_id}" @active = false if @reader_thread # run (resume from sleep) and wait for @reader_thread to end @reader_thread.run if @reader_thread.alive? @reader_thread.join @reader_thread = nil end ensure @action_threads.list.each do |thread| begin thread.kill thread.join rescue Exception => e logger.error "error when killing action thread: #{e.inspect}" end end nil end |