lib/launchpad/device.rb in launchpad-0.1.1 vs lib/launchpad/device.rb in launchpad-0.2.0

- old
+ new

@@ -117,11 +117,14 @@ # # [<tt>:x</tt>] x coordinate # [<tt>:y</tt>] y coordinate # [<tt>:red</tt>] brightness of red LED # [<tt>:green</tt>] brightness of green LED - # [<tt>:mode</tt>] button mode + # [<tt>:mode</tt>] button mode, defaults to <tt>:normal</tt>, one of: + # [<tt>:normal/tt>] updates the LED for all circumstances (the new value will be written to both buffers) + # [<tt>:flashing/tt>] updates the LED for flashing (the new value will be written to buffer 0 while the LED will be off in buffer 1, see buffering_mode) + # [<tt>:buffering/tt>] updates the LED for the current update_buffer only # # Errors raised: # # [Launchpad::NoValidGridCoordinatesError] when coordinates aren't within the valid range # [Launchpad::NoValidBrightnessError] when brightness values aren't within the valid range @@ -155,58 +158,73 @@ # [Launchpad::NoOutputAllowedError] when output is not enabled def change_all(*colors) # ensure that colors is at least and most 80 elements long colors = colors.flatten[0..79] colors += [0] * (80 - colors.size) if colors.size < 80 - # HACK switch off first grid LED to reset rapid LED change pointer - output(Status::ON, 0, 0) + # send normal MIDI message to reset rapid LED change pointer + # in this case, set mapping mode to x-y layout (the default) + output(Status::CC, Status::NIL, GridLayout::XY) # send colors in slices of 2 + messages = [] colors.each_slice(2) do |c1, c2| - output(Status::MULTI, velocity(c1), velocity(c2)) + messages << message(Status::MULTI, velocity(c1), velocity(c2)) end + output_messages(messages) end # Switches LEDs marked as flashing on when using custom timer for flashing. # # Errors raised: # # [Launchpad::NoOutputAllowedError] when output is not enabled def flashing_on - output(Status::CC, Status::NIL, Velocity::FLASHING_ON) + buffering_mode(:display_buffer => 0) end # Switches LEDs marked as flashing off when using custom timer for flashing. # # Errors raised: # # [Launchpad::NoOutputAllowedError] when output is not enabled def flashing_off - output(Status::CC, Status::NIL, Velocity::FLASHING_OFF) + buffering_mode(:display_buffer => 1) end # Starts flashing LEDs marked as flashing automatically. # Stop flashing by calling flashing_on or flashing_off. # # Errors raised: # # [Launchpad::NoOutputAllowedError] when output is not enabled def flashing_auto - output(Status::CC, Status::NIL, Velocity::FLASHING_AUTO) + buffering_mode(:flashing => true) end - # def start_buffering - # output(CC, 0x00, 0x31) - # @buffering = true - # end - # - # def flush_buffer(end_buffering = true) - # output(CC, 0x00, 0x34) - # if end_buffering - # output(CC, 0x00, 0x30) - # @buffering = false - # end - # end + # Controls the two buffers. + # + # Optional options hash: + # + # [<tt>:display_buffer</tt>] which buffer to use for display, defaults to +0+ + # [<tt>:update_buffer</tt>] which buffer to use for updates when <tt>:mode</tt> is set to <tt>:buffering</tt>, defaults to +0+ (see change) + # [<tt>:copy</tt>] whether to copy the LEDs states from the new display_buffer over to the new update_buffer, <tt>true/false</tt>, defaults to <tt>false</tt> + # [<tt>:flashing</tt>] whether to start flashing by automatically switching between the two buffers for display, <tt>true/false</tt>, defaults to <tt>false</tt> + # + # Errors raised: + # + # [Launchpad::NoOutputAllowedError] when output is not enabled + def buffering_mode(opts = nil) + opts = { + :display_buffer => 0, + :update_buffer => 0, + :copy => false, + :flashing => false + }.merge(opts || {}) + data = opts[:display_buffer] + 4 * opts[:update_buffer] + 32 + data += 16 if opts[:copy] + data += 8 if opts[:flashing] + output(Status::CC, Status::NIL, data) + end # Reads user actions (button presses/releases) that haven't been handled yet. # # Returns: # @@ -328,12 +346,26 @@ # # Errors raised: # # [Launchpad::NoOutputAllowedError] when output is not enabled def output(status, data1, data2) + output_messages([message(status, data1, data2)]) + end + + # Writes several messages to the MIDI device. + # + # Parameters: + # + # [+messages+] an array of hashes (usually created with message) with: + # [<tt>:message</tt>] an array of + # MIDI status code, + # MIDI data 1 (note), + # MIDI data 2 (velocity) + # [<tt>:timestamp</tt>] integer indicating the time when the MIDI message was created + def output_messages(messages) raise NoOutputAllowedError if @output.nil? - @output.write([{:message => [status, data1, data2], :timestamp => 0}]) + @output.write(messages) nil end # Calculates the MIDI data 1 value (note) for a button. # @@ -383,11 +415,14 @@ # # Options hash: # # [<tt>:red</tt>] brightness of red LED # [<tt>:green</tt>] brightness of green LED - # [<tt>:mode</tt>] button mode + # [<tt>:mode</tt>] button mode, defaults to <tt>:normal</tt>, one of: + # [<tt>:normal/tt>] updates the LED for all circumstances (the new value will be written to both buffers) + # [<tt>:flashing/tt>] updates the LED for flashing (the new value will be written to buffer 0 while in buffer 1, the value will be :off, see ) + # [<tt>:buffering/tt>] updates the LED for the current update_buffer only # # Returns: # # integer to be used for MIDI data 2 # @@ -426,9 +461,30 @@ when 2, :medium, :med then 2 when 3, :high, :hi then 3 else raise NoValidBrightnessError.new("you need to specify the brightness as 0/1/2/3, :off/:low/:medium/:high or :off/:lo/:hi, you specified: #{brightness}") end + end + + # Creates a MIDI message. + # + # Parameters: + # + # [+status+] MIDI status code + # [+data1+] MIDI data 1 (note) + # [+data2+] MIDI data 2 (velocity) + # + # Returns: + # + # an array with: + # + # [<tt>:message</tt>] an array of + # MIDI status code, + # MIDI data 1 (note), + # MIDI data 2 (velocity) + # [<tt>:timestamp</tt>] integer indicating the time when the MIDI message was created, in this case 0 + def message(status, data1, data2) + {:message => [status, data1, data2], :timestamp => 0} end end end