launchpad 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +26 -0
- data/Rakefile +57 -0
- data/examples/colors.rb +20 -0
- data/examples/feedback.rb +5 -0
- data/examples/setup.rb +4 -0
- data/experiments/wandering_dot.rb +116 -0
- data/launchpad.gemspec +61 -0
- data/lib/launchpad.rb +165 -0
- data/lib/launchpad/version.rb +3 -0
- data/test/helper.rb +10 -0
- data/test/test_launchpad-gem.rb +7 -0
- metadata +82 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Thomas Jachmann
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
= launchpad
|
2
|
+
|
3
|
+
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.
|
4
|
+
|
5
|
+
This is the first version, nothing sophisticated, but you can access the launchpad already. In and out. The API might change quite a bit during the next releases, so don't rely on it, this is work in progress. If you need anything or think the interface could be improved in any way, please contact me.
|
6
|
+
|
7
|
+
Sometimes, the launchpad won't react to anything. Don't despair, just dis- and reconnect the thing. It seems that some (unexpected) MIDI signals make it hickup.
|
8
|
+
|
9
|
+
|
10
|
+
== Requirements
|
11
|
+
|
12
|
+
* Jan Krutisch's portmidi gem
|
13
|
+
* Roger B. Dannenberg's portmidi library
|
14
|
+
|
15
|
+
|
16
|
+
== Near future plans
|
17
|
+
|
18
|
+
* dedicated interaction with control buttons (top and right row)
|
19
|
+
* listeners for presses on single buttons/button areas
|
20
|
+
* double buffering (already there but has some glitches)
|
21
|
+
* bitmap rendering
|
22
|
+
|
23
|
+
|
24
|
+
== Copyright
|
25
|
+
|
26
|
+
Copyright (c) 2009 Thomas Jachmann. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
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.add_dependency('portmidi')
|
17
|
+
#gem.add_development_dependency 'thoughtbot-shoulda', '>= 0'
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts 'Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler'
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/test_*.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort 'RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
task :test => :check_dependencies
|
46
|
+
|
47
|
+
task :default => :test
|
48
|
+
|
49
|
+
require 'rake/rdoctask'
|
50
|
+
Rake::RDocTask.new do |rdoc|
|
51
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "launchpad #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
data/examples/colors.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'setup')
|
2
|
+
|
3
|
+
l = Launchpad.new(:input => false, :output => true)
|
4
|
+
|
5
|
+
sleep 1
|
6
|
+
|
7
|
+
pos_x = pos_y = 0
|
8
|
+
4.times do |red|
|
9
|
+
4.times do |green|
|
10
|
+
l.single :x => pos_x, :y => pos_y, :red => red, :green => green, :mode => :buffering
|
11
|
+
l.single :x => 7 - pos_x, :y => pos_y, :red => red, :green => green, :mode => :buffering
|
12
|
+
l.single :x => pos_x, :y => 7 - pos_y, :red => red, :green => green, :mode => :buffering
|
13
|
+
l.single :x => 7 - pos_x, :y => 7 - pos_y, :red => red, :green => green, :mode => :buffering
|
14
|
+
pos_y += 1
|
15
|
+
end
|
16
|
+
pos_x += 1
|
17
|
+
pos_y = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
sleep 1
|
data/examples/setup.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'midiator'
|
3
|
+
|
4
|
+
@midi = MIDIator::Interface.new
|
5
|
+
@midi.autodetect_driver
|
6
|
+
|
7
|
+
def note_for(x, y)
|
8
|
+
y * 16 + x
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_all(&block)
|
12
|
+
(0..7).each do |row|
|
13
|
+
row_start = row * 16
|
14
|
+
(row_start..(row_start+7)).each(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def rand_pos
|
19
|
+
rand(8)
|
20
|
+
end
|
21
|
+
|
22
|
+
def rand_dir
|
23
|
+
rand(3) - 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def new_dir(dir, pos)
|
27
|
+
if (dir <= 0 && pos == 0) || pos == 7
|
28
|
+
new_dir = rand_dir.abs
|
29
|
+
new_dir = -new_dir if dir > 0
|
30
|
+
new_dir
|
31
|
+
else
|
32
|
+
dir
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def change_dir(dir, pos, change)
|
37
|
+
if (dir <= 0 && pos == 0) || pos == 7
|
38
|
+
-dir
|
39
|
+
elsif change
|
40
|
+
case dir
|
41
|
+
when -1 then -rand(2)
|
42
|
+
when 0 then rand(2) == 0 ? -1 : 1
|
43
|
+
when 1 then rand(2)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
dir
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def new_pos(pos, dir)
|
51
|
+
[0, [pos + dir, 7].min].max
|
52
|
+
end
|
53
|
+
|
54
|
+
def end_it
|
55
|
+
sleep 1
|
56
|
+
final_note = note_for(@pos_x, @pos_y)
|
57
|
+
4.times do
|
58
|
+
on_all {|note| @midi.note_on(note, 0, 1) unless note == final_note}
|
59
|
+
sleep 0.5
|
60
|
+
on_all {|note| @midi.note_on(note, 0, 16) unless note == final_note}
|
61
|
+
sleep 0.5
|
62
|
+
end
|
63
|
+
on_all {|note| @midi.note_off(note, 0)}
|
64
|
+
sleep 0.5
|
65
|
+
end
|
66
|
+
|
67
|
+
remaining_notes = []
|
68
|
+
on_all do |note|
|
69
|
+
remaining_notes << note
|
70
|
+
@midi.note_off(note, 0)
|
71
|
+
end
|
72
|
+
remaining_notes.uniq!
|
73
|
+
|
74
|
+
sleep (ARGV[0] || 0).to_i
|
75
|
+
|
76
|
+
@pos_x = rand_pos
|
77
|
+
@pos_y = rand_pos
|
78
|
+
@dir_x = rand_dir
|
79
|
+
@dir_y = rand_dir
|
80
|
+
|
81
|
+
new_note = note_for(@pos_x, @pos_y)
|
82
|
+
old_note = nil
|
83
|
+
|
84
|
+
on_all {|note| @midi.note_on(note, 0, 3)}
|
85
|
+
on_all {|note| @midi.note_off(note, 0) unless note == new_note}
|
86
|
+
|
87
|
+
sleep 2
|
88
|
+
sleep_time = 1
|
89
|
+
|
90
|
+
loop do
|
91
|
+
unless old_note == new_note || old_note.nil?
|
92
|
+
@midi.note_off(old_note, 0)
|
93
|
+
@midi.note_on(old_note, 0, 16)
|
94
|
+
@midi.note_on(new_note, 0, 3)
|
95
|
+
end
|
96
|
+
remaining_notes.delete(new_note)
|
97
|
+
end_it && break if remaining_notes.empty?
|
98
|
+
change = rand(1)
|
99
|
+
@dir_x = change_dir(@dir_x, @pos_x, change == 0)
|
100
|
+
@dir_y = change_dir(@dir_y, @pos_y, change != 0)
|
101
|
+
#@dir_x = new_dir(@dir_x, @pos_x)
|
102
|
+
#@dir_y = new_dir(@dir_y, @pos_y)
|
103
|
+
#while @dir_x == 0 && @dir_y == 0 || (old_note.nil? && (@dir_x == 0 || @dir_y == 0))
|
104
|
+
# if rand(1) == 0
|
105
|
+
# @dir_x = new_dir(@dir_x, @pos_x)
|
106
|
+
# else
|
107
|
+
# @dir_y = new_dir(@dir_y, @pos_y)
|
108
|
+
# end
|
109
|
+
#end
|
110
|
+
@pos_x = new_pos(@pos_x, @dir_x)
|
111
|
+
@pos_y = new_pos(@pos_y, @dir_y)
|
112
|
+
old_note = new_note
|
113
|
+
new_note = note_for(@pos_x, @pos_y)
|
114
|
+
sleep sleep_time
|
115
|
+
sleep_time *= 0.96
|
116
|
+
end
|
data/launchpad.gemspec
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{launchpad}
|
8
|
+
s.version = "0.0.1"
|
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{2009-11-08}
|
13
|
+
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/colors.rb",
|
26
|
+
"examples/feedback.rb",
|
27
|
+
"examples/setup.rb",
|
28
|
+
"experiments/wandering_dot.rb",
|
29
|
+
"launchpad.gemspec",
|
30
|
+
"lib/launchpad.rb",
|
31
|
+
"lib/launchpad/version.rb",
|
32
|
+
"test/helper.rb",
|
33
|
+
"test/test_launchpad-gem.rb"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/thomasjachmann/launchpad}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.5}
|
39
|
+
s.summary = %q{A gem for accessing novation's launchpad programmatically and easily.}
|
40
|
+
s.test_files = [
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_launchpad-gem.rb",
|
43
|
+
"examples/colors.rb",
|
44
|
+
"examples/feedback.rb",
|
45
|
+
"examples/setup.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_runtime_dependency(%q<portmidi>, [">= 0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<portmidi>, [">= 0"])
|
56
|
+
end
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<portmidi>, [">= 0"])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/lib/launchpad.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
class Launchpad
|
2
|
+
|
3
|
+
class LaunchpadError < StandardError; end
|
4
|
+
class NoInputAllowed < LaunchpadError; end
|
5
|
+
class NoOutputAllowed < LaunchpadError; end
|
6
|
+
class NoLocationError < LaunchpadError; end
|
7
|
+
class CommunicationError < LaunchpadError
|
8
|
+
attr_accessor :source
|
9
|
+
def initialize(e)
|
10
|
+
super(e.portmidi_error)
|
11
|
+
self.source = e
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
OFF = 0x80
|
16
|
+
ON = 0x90
|
17
|
+
CC = 0xB0
|
18
|
+
|
19
|
+
def initialize(opts = nil)
|
20
|
+
opts = {
|
21
|
+
:device_name => 'Launchpad',
|
22
|
+
:input => true,
|
23
|
+
:output => true
|
24
|
+
}.merge(opts || {})
|
25
|
+
Portmidi.start
|
26
|
+
if opts[:input]
|
27
|
+
input_device = Portmidi.input_devices.select {|device| device.name == opts[:device_name]}.first
|
28
|
+
@input = Portmidi::Input.new(input_device.device_id)
|
29
|
+
end
|
30
|
+
if opts[:output]
|
31
|
+
output_device = Portmidi.output_devices.select {|device| device.name == opts[:device_name]}.first
|
32
|
+
@output = Portmidi::Output.new(output_device.device_id)
|
33
|
+
reset
|
34
|
+
end
|
35
|
+
@buffering = false
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.start(opts = nil, &block)
|
39
|
+
opts ||= {}
|
40
|
+
latency = (opts.delete(:latency) || 0.001).to_f
|
41
|
+
launchpad = Launchpad.new(opts.merge({:input => true, :output => true}))
|
42
|
+
loop do
|
43
|
+
messages = launchpad.input
|
44
|
+
if messages
|
45
|
+
messages.each do |message|
|
46
|
+
message = parse_message(message)
|
47
|
+
if message[:code] == ON
|
48
|
+
block.call(launchpad, message[:x], message[:y], message[:state])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
sleep latency
|
53
|
+
end
|
54
|
+
rescue Portmidi::DeviceError => e
|
55
|
+
raise CommunicationError.new(e)
|
56
|
+
ensure
|
57
|
+
launchpad.reset if launchpad
|
58
|
+
end
|
59
|
+
|
60
|
+
# Reset the launchpad - all settings are reset and all LEDs are switched off
|
61
|
+
def reset
|
62
|
+
output(CC, 0x00, 0x00)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Light all LEDs (for testing purposes)
|
66
|
+
# takes an optional parameter brightness (1-3, defaults to 3)
|
67
|
+
def light_all(brightness = 3)
|
68
|
+
output(CC, 0x00, 124 + min_max_color(brightness, false))
|
69
|
+
end
|
70
|
+
|
71
|
+
def start_buffering
|
72
|
+
output(CC, 0x00, 0x31)
|
73
|
+
@buffering = true
|
74
|
+
end
|
75
|
+
|
76
|
+
def flush_buffer(end_buffering = true)
|
77
|
+
output(CC, 0x00, 0x34)
|
78
|
+
if end_buffering
|
79
|
+
output(CC, 0x00, 0x30)
|
80
|
+
@buffering = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Switches a single LED
|
85
|
+
# * :x => x coordinate (0 based from top left, mandatory)
|
86
|
+
# * :y => y coordinate (0 based from top left, mandatory)
|
87
|
+
# * :red => brightness of red LED (0-3, optional, defaults to 0)
|
88
|
+
# * :green => brightness of red LED (0-3, optional, defaults to 0)
|
89
|
+
# * :mode => button behaviour (:normal, :flashing, :buffering, optional, defaults to :normal)
|
90
|
+
def single(opts)
|
91
|
+
location = location(opts)
|
92
|
+
velocity = velocity(opts)
|
93
|
+
output(ON, location, velocity)
|
94
|
+
end
|
95
|
+
|
96
|
+
def multi(*velocities)
|
97
|
+
output(CC, 0x01, 0x00)
|
98
|
+
output(0x92, *velocities)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Switches LEDs marked as flashing on (when using custom timer for flashing)
|
102
|
+
def custom_flashing_on
|
103
|
+
output(CC, 0x00, 0x20)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Switches LEDs marked as flashing off (when using custom timer for flashing)
|
107
|
+
def custom_flashing_off
|
108
|
+
output(CC, 0x00, 0x21)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Starts flashing LEDs marked as flashing automatically
|
112
|
+
def start_auto_flashing
|
113
|
+
output(CC, 0x00, 0x28)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Stops flashing LEDs marked as flashing automatically (turning them on)
|
117
|
+
alias_method :stop_auto_flashing, :custom_flashing_on
|
118
|
+
|
119
|
+
def coordinates(location)
|
120
|
+
[location % 16, location / 16]
|
121
|
+
end
|
122
|
+
|
123
|
+
def input
|
124
|
+
raise NoInputAllowed if @input.nil?
|
125
|
+
@input.read(16)
|
126
|
+
end
|
127
|
+
|
128
|
+
def output(*args)
|
129
|
+
raise NoOutputAllowed if @output.nil?
|
130
|
+
@output.write([{:message => args, :timestamp => 0}])
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def self.parse_message(message)
|
136
|
+
message = message[:message]
|
137
|
+
{
|
138
|
+
:code => message[0],
|
139
|
+
:x => message[1] % 16,
|
140
|
+
:y => message[1] / 16,
|
141
|
+
:state => message[2] == 127
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def location(opts)
|
146
|
+
raise NoLocationError.new('you need to specify a location (x/y, 0 based from top left)') if (y = opts[:y]).nil? || (x = opts[:x]).nil?
|
147
|
+
y * 16 + x
|
148
|
+
end
|
149
|
+
|
150
|
+
def velocity(opts)
|
151
|
+
red = min_max_color(opts[:red] || 0)
|
152
|
+
green = min_max_color(opts[:green] || 0)
|
153
|
+
flags = case opts[:mode]
|
154
|
+
when :flashing then 8
|
155
|
+
when :buffering then 0
|
156
|
+
else 12
|
157
|
+
end
|
158
|
+
(16 * (green)) + red + flags
|
159
|
+
end
|
160
|
+
|
161
|
+
def min_max_color(color, with_off = true)
|
162
|
+
[[with_off ? 0 : 1, color.to_i].max, 3].min
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: launchpad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Jachmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-08 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: portmidi
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
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.
|
26
|
+
email: tom.j@gmx.net
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- examples/colors.rb
|
41
|
+
- examples/feedback.rb
|
42
|
+
- examples/setup.rb
|
43
|
+
- experiments/wandering_dot.rb
|
44
|
+
- launchpad.gemspec
|
45
|
+
- lib/launchpad.rb
|
46
|
+
- lib/launchpad/version.rb
|
47
|
+
- test/helper.rb
|
48
|
+
- test/test_launchpad-gem.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/thomasjachmann/launchpad
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: A gem for accessing novation's launchpad programmatically and easily.
|
77
|
+
test_files:
|
78
|
+
- test/helper.rb
|
79
|
+
- test/test_launchpad-gem.rb
|
80
|
+
- examples/colors.rb
|
81
|
+
- examples/feedback.rb
|
82
|
+
- examples/setup.rb
|