launchpad 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
- rdoc
2
- pkg
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ - 2.0.0
6
+ before_install:
7
+ - sudo apt-get update
8
+ - sudo apt-get install libportmidi-dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in launchpad.gemspec
4
+ gemspec
@@ -1,26 +1,46 @@
1
1
  = launchpad
2
2
 
3
- This gem provides an interface to access novation's launchpad programmatically. LEDs can be lighted and button presses can be responded to. Internally, launchpad's MIDI input/output is used to accomplish this.
3
+ {<img src="https://travis-ci.org/thomasjachmann/launchpad.png?branch=master" alt="Build Status" />}[https://travis-ci.org/thomasjachmann/launchpad]
4
+
5
+ This gem provides a ruby interface to access novation's launchpad programmatically. LEDs can be lighted and button presses can be responded to. Internally, launchpad's MIDI input/output is used to accomplish this.
4
6
 
5
7
  The interfaces should be rather stable now (sorry, I changed quite a bit since the last release), so experiment with them and comment on their usability. This still is work in progress. If you need anything or think the interfaces could be improved in any way, please contact me.
6
8
 
7
9
  Sometimes, the launchpad won't react to anything or react to/light up the wrong LEDs. Don't despair, just dis- and reconnect the thing. It seems that some (unexpected) MIDI signals make it hickup.
8
10
 
9
11
 
12
+ == More Info
13
+
14
+ If you don't know what launchpad is, visit:
15
+
16
+ * Novation's site at http://de.novationmusic.com/products/midi_controller/launchpad
17
+ * my demo videos for this library at http://www.youtube.com/thomasjachmann
18
+ * other demos on youtube http://www.youtube.com/results?search_query=novation+launchpad
19
+
20
+ If you're into other languages or want to know what goes on behind the scenes MIDI wise, have a look at:
21
+
22
+ * Novation's MIDI programmer's reference at {www.novationmusic.com/support/launchpad}[http://www.novationmusic.com/support/launchpad/] (bottom of the page)
23
+ * Tobi Tobes' port of my gem to processing at http://github.com/rngtng/launchpad
24
+
25
+
10
26
  == Requirements
11
27
 
12
28
  * Roger B. Dannenberg's {portmidi library}[http://sourceforge.net/projects/portmedia/]
13
29
  * Jan Krutisch's {portmidi gem}[http://github.com/halfbyte/portmidi]
14
30
 
15
31
 
16
- == Installation
32
+ == Compatibility
33
+
34
+ The gem is known to be compatible with the following ruby versions:
35
+
36
+ * MRI 1.8.7
37
+ * MRI 1.9.3
38
+ * MRI 2.0.0
17
39
 
18
- The gem is hosted on Gemcutter[http://gemcutter.org/], so in order to use it, you're gonna install the gemcutter gem (for details, see their site):
19
40
 
20
- gem install gemcutter
21
- gem tumble
41
+ == Installation
22
42
 
23
- After that, it's a simple gem install:
43
+ The gem is hosted on RubyGems[https://rubygems.org/], so in order to use it, you're gonna gem install it:
24
44
 
25
45
  gem install launchpad
26
46
 
@@ -34,7 +54,6 @@ There are two main entry points:
34
54
 
35
55
  This is a simple example (only requiring the device for output) that switches on all LEDs (for testing), resets the launchpad again and then lights the grid button at position 4/4 (from top left).
36
56
 
37
- require 'rubygems'
38
57
  require 'launchpad/device'
39
58
 
40
59
  device = Launchpad::Device.new
@@ -46,7 +65,6 @@ This is a simple example (only requiring the device for output) that switches on
46
65
 
47
66
  This is an interaction example lighting all grid buttons in red when pressed and keeping them lit.
48
67
 
49
- require 'rubygems'
50
68
  require 'launchpad'
51
69
 
52
70
  interaction = Launchpad::Interaction.new
@@ -63,15 +81,21 @@ This is an interaction example lighting all grid buttons in red when pressed and
63
81
  For more details, see the examples. examples/color_picker.rb is the most complex example with interaction.
64
82
 
65
83
 
66
- == Near future plans
84
+ == Future plans
67
85
 
68
- * interaction responses for presses on single grid buttons/button areas
69
86
  * bitmap rendering
70
87
  * internal tracking of LED states for both buffers
71
88
 
72
89
 
73
90
  == Changelog
74
91
 
92
+ === v.0.3.0
93
+
94
+ * logging
95
+ * reworked multi threading for action handling
96
+ * compatibility with ruby 1.8.7 and 2.0.0
97
+ * interaction responses for presses on single grid buttons/button areas/columns/rows
98
+
75
99
  === v.0.2.2
76
100
 
77
101
  * single threading fix: prevent ThreadError when Launchpad::Interaction#stop is called within an action response
data/Rakefile CHANGED
@@ -1,28 +1,4 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- require File.join(File.dirname(__FILE__), 'lib', 'launchpad', 'version')
5
-
6
- begin
7
- require 'jeweler'
8
- Jeweler::Tasks.new do |gem|
9
- gem.name = 'launchpad'
10
- gem.summary = 'A gem for accessing novation\'s launchpad programmatically and easily.'
11
- gem.description = 'This gem provides an interface to access novation\'s launchpad programmatically. LEDs can be lighted and button presses can be evaluated using launchpad\'s MIDI input/output.'
12
- gem.email = 'tom.j@gmx.net'
13
- gem.homepage = 'http://github.com/thomasjachmann/launchpad'
14
- gem.version = Launchpad::VERSION
15
- gem.authors = ['Thomas Jachmann']
16
- gem.has_rdoc = true
17
- gem.add_dependency('portmidi', '>= 0.0.6')
18
- gem.add_development_dependency('thoughtbot-shoulda', '>= 0')
19
- gem.add_development_dependency('mocha')
20
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
- end
22
- Jeweler::GemcutterTasks.new
23
- rescue LoadError
24
- puts 'Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler'
25
- end
1
+ require 'bundler/gem_tasks'
26
2
 
27
3
  require 'rake/testtask'
28
4
  Rake::TestTask.new(:test) do |test|
@@ -31,29 +7,4 @@ Rake::TestTask.new(:test) do |test|
31
7
  test.verbose = true
32
8
  end
33
9
 
34
- begin
35
- require 'rcov/rcovtask'
36
- Rcov::RcovTask.new do |test|
37
- test.libs << 'test'
38
- test.pattern = 'test/**/test_*.rb'
39
- test.verbose = true
40
- end
41
- rescue LoadError
42
- task :rcov do
43
- abort 'RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov'
44
- end
45
- end
46
-
47
- task :test => :check_dependencies
48
-
49
10
  task :default => :test
50
-
51
- require 'rake/rdoctask'
52
- Rake::RDocTask.new do |rdoc|
53
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
54
-
55
- rdoc.rdoc_dir = 'rdoc'
56
- rdoc.title = "launchpad #{version}"
57
- rdoc.rdoc_files.include('README*')
58
- rdoc.rdoc_files.include('lib/**/*.rb')
59
- end
@@ -0,0 +1,29 @@
1
+ require 'launchpad'
2
+
3
+ device = Launchpad::Device.new
4
+
5
+ on = { :red => :high, :green => :off }
6
+ off = { :red => :off, :green => :lo }
7
+
8
+ digit_map = [
9
+ [off, off, off, off],
10
+ [on , off, off, off],
11
+ [off, on , off, off],
12
+ [on , on , off, off],
13
+ [off, off, on , off],
14
+ [on , off, on , off],
15
+ [off, on , on , off],
16
+ [on , on , on , off],
17
+ [off, off, off, on ],
18
+ [on , off, off, on ]
19
+ ]
20
+
21
+ while true do
22
+ Time.now.strftime('%H%M%S').split('').each_with_index do |digit, x|
23
+ digit_map[digit.to_i].each_with_index do |color, y|
24
+ device.change :grid, color.merge(:x => x, :y => (7 - y))
25
+ end
26
+ end
27
+
28
+ sleep 0.25
29
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  interaction = Launchpad::Interaction.new
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  device = Launchpad::Device.new(:input => false, :output => true)
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  interaction = Launchpad::Interaction.new
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  interaction = Launchpad::Interaction.new
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  interaction = Launchpad::Interaction.new
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  interaction = Launchpad::Interaction.new
4
4
 
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
1
+ require 'launchpad'
2
2
 
3
3
  Launchpad::Device.new.reset
4
4
 
@@ -1,83 +1,34 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "launchpad/version"
5
4
 
6
5
  Gem::Specification.new do |s|
7
- s.name = %q{launchpad}
8
- s.version = "0.2.2"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Thomas Jachmann"]
12
- s.date = %q{2010-02-24}
6
+ s.name = "launchpad"
7
+ s.version = Launchpad::VERSION
8
+ s.authors = ["Thomas Jachmann"]
9
+ s.email = ["self@thomasjachmann.com"]
10
+ s.homepage = "https://github.com/thomasjachmann/launchpad"
11
+ s.summary = %q{A gem for accessing novation's launchpad programmatically and easily.}
13
12
  s.description = %q{This gem provides an interface to access novation's launchpad programmatically. LEDs can be lighted and button presses can be evaluated using launchpad's MIDI input/output.}
14
- s.email = %q{tom.j@gmx.net}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".gitignore",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "examples/color_picker.rb",
26
- "examples/colors.rb",
27
- "examples/doodle.rb",
28
- "examples/double_buffering.rb",
29
- "examples/drawing_board.rb",
30
- "examples/feedback.rb",
31
- "examples/reset.rb",
32
- "examples/setup.rb",
33
- "experiments/wandering_dot.rb",
34
- "launchpad.gemspec",
35
- "lib/launchpad.rb",
36
- "lib/launchpad/device.rb",
37
- "lib/launchpad/errors.rb",
38
- "lib/launchpad/interaction.rb",
39
- "lib/launchpad/midi_codes.rb",
40
- "lib/launchpad/version.rb",
41
- "test/helper.rb",
42
- "test/test_device.rb",
43
- "test/test_interaction.rb"
44
- ]
45
- s.homepage = %q{http://github.com/thomasjachmann/launchpad}
46
- s.rdoc_options = ["--charset=UTF-8"]
47
- s.require_paths = ["lib"]
48
- s.rubygems_version = %q{1.3.5}
49
- s.summary = %q{A gem for accessing novation's launchpad programmatically and easily.}
50
- s.test_files = [
51
- "test/helper.rb",
52
- "test/test_device.rb",
53
- "test/test_interaction.rb",
54
- "examples/color_picker.rb",
55
- "examples/colors.rb",
56
- "examples/doodle.rb",
57
- "examples/double_buffering.rb",
58
- "examples/drawing_board.rb",
59
- "examples/feedback.rb",
60
- "examples/reset.rb",
61
- "examples/setup.rb"
62
- ]
63
13
 
64
- if s.respond_to? :specification_version then
65
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
66
- s.specification_version = 3
14
+ s.rubyforge_project = "launchpad"
67
15
 
68
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
69
- s.add_runtime_dependency(%q<portmidi>, [">= 0.0.6"])
70
- s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
71
- s.add_development_dependency(%q<mocha>, [">= 0"])
72
- else
73
- s.add_dependency(%q<portmidi>, [">= 0.0.6"])
74
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
75
- s.add_dependency(%q<mocha>, [">= 0"])
76
- end
16
+ s.add_dependency "portmidi", ">= 0.0.6"
17
+ s.add_dependency "ffi"
18
+ s.add_development_dependency "rake"
19
+ if RUBY_VERSION < "1.9"
20
+ s.add_development_dependency "minitest"
21
+ # s.add_development_dependency "ruby-debug"
77
22
  else
78
- s.add_dependency(%q<portmidi>, [">= 0.0.6"])
79
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
80
- s.add_dependency(%q<mocha>, [">= 0"])
23
+ s.add_development_dependency "minitest-reporters"
24
+ # s.add_development_dependency "debugger"
81
25
  end
82
- end
26
+ s.add_development_dependency "mocha"
83
27
 
28
+ # s.has_rdoc = true
29
+
30
+ s.files = `git ls-files`.split("\n")
31
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
33
+ s.require_paths = ["lib"]
34
+ end
@@ -30,4 +30,5 @@ require 'launchpad/interaction'
30
30
  # * <tt>:buffering</tt> (LED is written to buffer, see Launchpad::Device.start_buffering, Launchpad::Device.flush_buffer)
31
31
  # optional, defaults to <tt>:normal</tt>
32
32
  # [+state+] whether the button is pressed or released, <tt>:down/:up</tt>
33
- module Launchpad; end
33
+ module Launchpad
34
+ end
@@ -1,6 +1,7 @@
1
1
  require 'portmidi'
2
2
 
3
3
  require 'launchpad/errors'
4
+ require 'launchpad/logging'
4
5
  require 'launchpad/midi_codes'
5
6
  require 'launchpad/version'
6
7
 
@@ -11,7 +12,6 @@ module Launchpad
11
12
  #
12
13
  # Example:
13
14
  #
14
- # require 'rubygems'
15
15
  # require 'launchpad/device'
16
16
  #
17
17
  # device = Launchpad::Device.new
@@ -22,8 +22,47 @@ module Launchpad
22
22
  # device.change :grid, :x => 4, :y => 4, :red => :high, :green => :low
23
23
  class Device
24
24
 
25
+ include Logging
25
26
  include MidiCodes
26
27
 
28
+ CODE_NOTE_TO_DATA_TYPE = {
29
+ [Status::ON, SceneButton::SCENE1] => :scene1,
30
+ [Status::ON, SceneButton::SCENE2] => :scene2,
31
+ [Status::ON, SceneButton::SCENE3] => :scene3,
32
+ [Status::ON, SceneButton::SCENE4] => :scene4,
33
+ [Status::ON, SceneButton::SCENE5] => :scene5,
34
+ [Status::ON, SceneButton::SCENE6] => :scene6,
35
+ [Status::ON, SceneButton::SCENE7] => :scene7,
36
+ [Status::ON, SceneButton::SCENE8] => :scene8,
37
+ [Status::CC, ControlButton::UP] => :up,
38
+ [Status::CC, ControlButton::DOWN] => :down,
39
+ [Status::CC, ControlButton::LEFT] => :left,
40
+ [Status::CC, ControlButton::RIGHT] => :right,
41
+ [Status::CC, ControlButton::SESSION] => :session,
42
+ [Status::CC, ControlButton::USER1] => :user1,
43
+ [Status::CC, ControlButton::USER2] => :user2,
44
+ [Status::CC, ControlButton::MIXER] => :mixer
45
+ }.freeze
46
+
47
+ TYPE_TO_NOTE = {
48
+ :up => ControlButton::UP,
49
+ :down => ControlButton::DOWN,
50
+ :left => ControlButton::LEFT,
51
+ :right => ControlButton::RIGHT,
52
+ :session => ControlButton::SESSION,
53
+ :user1 => ControlButton::USER1,
54
+ :user2 => ControlButton::USER2,
55
+ :mixer => ControlButton::MIXER,
56
+ :scene1 => SceneButton::SCENE1,
57
+ :scene2 => SceneButton::SCENE2,
58
+ :scene3 => SceneButton::SCENE3,
59
+ :scene4 => SceneButton::SCENE4,
60
+ :scene5 => SceneButton::SCENE5,
61
+ :scene6 => SceneButton::SCENE6,
62
+ :scene7 => SceneButton::SCENE7,
63
+ :scene8 => SceneButton::SCENE8
64
+ }.freeze
65
+
27
66
  # Initializes the launchpad device. When output capabilities are requested,
28
67
  # the launchpad will be reset.
29
68
  #
@@ -39,6 +78,7 @@ module Launchpad
39
78
  # optional, <tt>:device_name</tt> will be used if omitted
40
79
  # [<tt>:device_name</tt>] Name of the MIDI device to use,
41
80
  # optional, defaults to "Launchpad"
81
+ # [<tt>:logger</tt>] [Logger] to be used by this device instance, can be changed afterwards
42
82
  #
43
83
  # Errors raised:
44
84
  #
@@ -50,15 +90,26 @@ module Launchpad
50
90
  :output => true
51
91
  }.merge(opts || {})
52
92
 
93
+ self.logger = opts[:logger]
94
+ logger.debug "initializing Launchpad::Device##{object_id} with #{opts.inspect}"
95
+
53
96
  Portmidi.start
54
97
 
55
- @input = device(Portmidi.input_devices, Portmidi::Input, :id => opts[:input_device_id], :name => opts[:device_name]) if opts[:input]
56
- @output = device(Portmidi.output_devices, Portmidi::Output, :id => opts[:output_device_id], :name => opts[:device_name]) if opts[:output]
98
+ @input = create_device!(Portmidi.input_devices, Portmidi::Input,
99
+ :id => opts[:input_device_id],
100
+ :name => opts[:device_name]
101
+ ) if opts[:input]
102
+ @output = create_device!(Portmidi.output_devices, Portmidi::Output,
103
+ :id => opts[:output_device_id],
104
+ :name => opts[:device_name]
105
+ ) if opts[:output]
106
+
57
107
  reset if output_enabled?
58
108
  end
59
109
 
60
110
  # Closes the device - nothing can be done with the device afterwards.
61
111
  def close
112
+ logger.debug "closing Launchpad::Device##{object_id}"
62
113
  @input.close unless @input.nil?
63
114
  @input = nil
64
115
  @output.close unless @output.nil?
@@ -228,6 +279,7 @@ module Launchpad
228
279
  end
229
280
 
230
281
  # Reads user actions (button presses/releases) that haven't been handled yet.
282
+ # This is non-blocking, so when nothing happend yet you'll get an empty array.
231
283
  #
232
284
  # Returns:
233
285
  #
@@ -249,33 +301,10 @@ module Launchpad
249
301
  :timestamp => midi_message[:timestamp],
250
302
  :state => (velocity == 127 ? :down : :up)
251
303
  }
252
- data[:type] = case code
253
- when Status::ON
254
- case note
255
- when SceneButton::SCENE1 then :scene1
256
- when SceneButton::SCENE2 then :scene2
257
- when SceneButton::SCENE3 then :scene3
258
- when SceneButton::SCENE4 then :scene4
259
- when SceneButton::SCENE5 then :scene5
260
- when SceneButton::SCENE6 then :scene6
261
- when SceneButton::SCENE7 then :scene7
262
- when SceneButton::SCENE8 then :scene8
263
- else
264
- data[:x] = note % 16
265
- data[:y] = note / 16
266
- :grid
267
- end
268
- when Status::CC
269
- case note
270
- when ControlButton::UP then :up
271
- when ControlButton::DOWN then :down
272
- when ControlButton::LEFT then :left
273
- when ControlButton::RIGHT then :right
274
- when ControlButton::SESSION then :session
275
- when ControlButton::USER1 then :user1
276
- when ControlButton::USER2 then :user2
277
- when ControlButton::MIXER then :mixer
278
- end
304
+ data[:type] = CODE_NOTE_TO_DATA_TYPE[[code, note]] || :grid
305
+ if data[:type] == :grid
306
+ data[:x] = note % 16
307
+ data[:y] = note / 16
279
308
  end
280
309
  data
281
310
  end
@@ -305,16 +334,22 @@ module Launchpad
305
334
  #
306
335
  # [Launchpad::NoSuchDeviceError] when device with ID or name specified does not exist
307
336
  # [Launchpad::DeviceBusyError] when device with ID or name specified is busy
308
- def device(devices, device_type, opts)
337
+ def create_device!(devices, device_type, opts)
338
+ logger.debug "creating #{device_type} with #{opts.inspect}, choosing from portmidi devices #{devices.inspect}"
309
339
  id = opts[:id]
310
340
  if id.nil?
311
341
  name = opts[:name] || 'Launchpad'
312
342
  device = devices.select {|device| device.name == name}.first
313
343
  id = device.device_id unless device.nil?
314
344
  end
315
- raise NoSuchDeviceError.new("MIDI device #{opts[:id] || opts[:name]} doesn't exist") if id.nil?
345
+ if id.nil?
346
+ message = "MIDI device #{opts[:id] || opts[:name]} doesn't exist"
347
+ logger.fatal message
348
+ raise NoSuchDeviceError.new(message)
349
+ end
316
350
  device_type.new(id)
317
351
  rescue RuntimeError => e
352
+ logger.fatal "error creating #{device_type}: #{e.inspect}"
318
353
  raise DeviceBusyError.new(e)
319
354
  end
320
355
 
@@ -335,7 +370,10 @@ module Launchpad
335
370
  #
336
371
  # [Launchpad::NoInputAllowedError] when output is not enabled
337
372
  def input
338
- raise NoInputAllowedError if @input.nil?
373
+ if @input.nil?
374
+ logger.error "trying to read from device that's not been initialized for input"
375
+ raise NoInputAllowedError
376
+ end
339
377
  @input.read(16)
340
378
  end
341
379
 
@@ -365,7 +403,11 @@ module Launchpad
365
403
  # MIDI data 2 (velocity)
366
404
  # [<tt>:timestamp</tt>] integer indicating the time when the MIDI message was created
367
405
  def output_messages(messages)
368
- raise NoOutputAllowedError if @output.nil?
406
+ if @output.nil?
407
+ logger.error "trying to write to device that's not been initialized for output"
408
+ raise NoOutputAllowedError
409
+ end
410
+ logger.debug "writing messages to launchpad:\n #{messages.join("\n ")}" if logger.debug?
369
411
  @output.write(messages)
370
412
  nil
371
413
  end
@@ -389,29 +431,17 @@ module Launchpad
389
431
  #
390
432
  # [Launchpad::NoValidGridCoordinatesError] when coordinates aren't within the valid range
391
433
  def note(type, opts)
392
- case type
393
- when :up then ControlButton::UP
394
- when :down then ControlButton::DOWN
395
- when :left then ControlButton::LEFT
396
- when :right then ControlButton::RIGHT
397
- when :session then ControlButton::SESSION
398
- when :user1 then ControlButton::USER1
399
- when :user2 then ControlButton::USER2
400
- when :mixer then ControlButton::MIXER
401
- when :scene1 then SceneButton::SCENE1
402
- when :scene2 then SceneButton::SCENE2
403
- when :scene3 then SceneButton::SCENE3
404
- when :scene4 then SceneButton::SCENE4
405
- when :scene5 then SceneButton::SCENE5
406
- when :scene6 then SceneButton::SCENE6
407
- when :scene7 then SceneButton::SCENE7
408
- when :scene8 then SceneButton::SCENE8
409
- else
434
+ note = TYPE_TO_NOTE[type]
435
+ if note.nil?
410
436
  x = (opts[:x] || -1).to_i
411
437
  y = (opts[:y] || -1).to_i
412
- raise NoValidGridCoordinatesError.new("you need to specify valid coordinates (x/y, 0-7, from top left), you specified: x=#{x}, y=#{y}") if x < 0 || x > 7 || y < 0 || y > 7
413
- y * 16 + x
438
+ if x < 0 || x > 7 || y < 0 || y > 7
439
+ logger.error "wrong coordinates specified: x=#{x}, y=#{y}"
440
+ raise NoValidGridCoordinatesError.new("you need to specify valid coordinates (x/y, 0-7, from top left), you specified: x=#{x}, y=#{y}")
441
+ end
442
+ note = y * 16 + x
414
443
  end
444
+ note
415
445
  end
416
446
 
417
447
  # Calculates the MIDI data 2 value (velocity) for given brightness and mode values.
@@ -433,19 +463,19 @@ module Launchpad
433
463
  #
434
464
  # [Launchpad::NoValidBrightnessError] when brightness values aren't within the valid range
435
465
  def velocity(opts)
436
- color = if opts.is_a?(Hash)
466
+ if opts.is_a?(Hash)
437
467
  red = brightness(opts[:red] || 0)
438
468
  green = brightness(opts[:green] || 0)
439
- 16 * green + red
469
+ color = 16 * green + red
470
+ flags = case opts[:mode]
471
+ when :flashing then 8
472
+ when :buffering then 0
473
+ else 12
474
+ end
475
+ color + flags
440
476
  else
441
- opts.to_i
442
- end
443
- flags = case opts[:mode]
444
- when :flashing then 8
445
- when :buffering then 0
446
- else 12
477
+ opts.to_i + 12
447
478
  end
448
- color + flags
449
479
  end
450
480
 
451
481
  # Calculates the integer brightness for given brightness values.
@@ -464,6 +494,7 @@ module Launchpad
464
494
  when 2, :medium, :med then 2
465
495
  when 3, :high, :hi then 3
466
496
  else
497
+ logger.error "wrong brightness specified: #{brightness}"
467
498
  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}")
468
499
  end
469
500
  end