sparkle_motion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE +22 -0
  4. data/README.md +47 -0
  5. data/bin/sm-discover +18 -0
  6. data/bin/sm-mark-lights +58 -0
  7. data/bin/sm-off +38 -0
  8. data/bin/sm-on +50 -0
  9. data/bin/sm-simulate +595 -0
  10. data/bin/sm-watch-memory +9 -0
  11. data/bin/sparkle-motion +48 -0
  12. data/config.yml +201 -0
  13. data/data/dynamic/bridges.csv +5 -0
  14. data/data/static/devices.csv +7 -0
  15. data/lib/sparkle_motion.rb +72 -0
  16. data/lib/sparkle_motion/config.rb +45 -0
  17. data/lib/sparkle_motion/env.rb +14 -0
  18. data/lib/sparkle_motion/http.rb +26 -0
  19. data/lib/sparkle_motion/hue/ssdp.rb +39 -0
  20. data/lib/sparkle_motion/launch_pad/color.rb +41 -0
  21. data/lib/sparkle_motion/launch_pad/widget.rb +187 -0
  22. data/lib/sparkle_motion/launch_pad/widgets/button.rb +29 -0
  23. data/lib/sparkle_motion/launch_pad/widgets/horizontal_slider.rb +43 -0
  24. data/lib/sparkle_motion/launch_pad/widgets/radio_group.rb +53 -0
  25. data/lib/sparkle_motion/launch_pad/widgets/toggle.rb +48 -0
  26. data/lib/sparkle_motion/launch_pad/widgets/vertical_slider.rb +43 -0
  27. data/lib/sparkle_motion/lazy_request_config.rb +87 -0
  28. data/lib/sparkle_motion/node.rb +80 -0
  29. data/lib/sparkle_motion/nodes/generator.rb +8 -0
  30. data/lib/sparkle_motion/nodes/generators/const.rb +15 -0
  31. data/lib/sparkle_motion/nodes/generators/perlin.rb +26 -0
  32. data/lib/sparkle_motion/nodes/generators/wave2.rb +20 -0
  33. data/lib/sparkle_motion/nodes/transform.rb +34 -0
  34. data/lib/sparkle_motion/nodes/transforms/contrast.rb +20 -0
  35. data/lib/sparkle_motion/nodes/transforms/range.rb +41 -0
  36. data/lib/sparkle_motion/nodes/transforms/spotlight.rb +35 -0
  37. data/lib/sparkle_motion/output.rb +69 -0
  38. data/lib/sparkle_motion/results.rb +78 -0
  39. data/lib/sparkle_motion/utility.rb +68 -0
  40. data/lib/sparkle_motion/vector2.rb +11 -0
  41. data/lib/sparkle_motion/version.rb +3 -0
  42. data/sparkle_motion.gemspec +44 -0
  43. metadata +178 -0
@@ -0,0 +1,78 @@
1
+ # TODO: Namespacing/classes/etc!
2
+
3
+ # Helper class to hold onto stats about requests made to the bridges.
4
+ #
5
+ # NOTE: Methods ending with `!` are *not* thread-safe, methods without it *are*.
6
+ #
7
+ # TODO: Track things by light index, bridge, etc...
8
+ class Results
9
+ attr_reader :start_time, :end_time, :successes, :failures, :hard_timeouts,
10
+ :soft_timeouts
11
+
12
+ def initialize(logger:)
13
+ @logger = logger
14
+ @mutex = Mutex.new
15
+ clear!
16
+ end
17
+
18
+ def clear!
19
+ @successes = 0
20
+ @failures = 0
21
+ @hard_timeouts = 0
22
+ @soft_timeouts = 0
23
+ end
24
+
25
+ def begin!; @start_time ||= Time.now.to_f; end
26
+ def done!; @end_time ||= Time.now.to_f; end
27
+
28
+ # TODO: Colorized output for all feedback types, or running counters, or
29
+ # TODO: something...
30
+
31
+ def success!(info = nil)
32
+ @logger.error { info } if info
33
+ @successes += 1
34
+ end
35
+
36
+ def failure!(info = nil)
37
+ @logger.error { info } if info
38
+ @failures += 1
39
+ end
40
+
41
+ def hard_timeout!(info = nil)
42
+ @logger.error { info } if info
43
+ @hard_timeouts += 1
44
+ end
45
+
46
+ def soft_timeout!(info = nil)
47
+ @logger.error { info } if info
48
+ @soft_timeouts += 1
49
+ end
50
+
51
+ def elapsed; @end_time - @start_time; end
52
+ def requests; @successes + @failures + @hard_timeouts + @soft_timeouts; end
53
+ def all_failures; @failures + @hard_timeouts + @soft_timeouts; end
54
+
55
+ def requests_sec; ratio(requests, elapsed); end
56
+ def successes_sec; ratio(successes, elapsed); end
57
+ def failures_sec; ratio(failures, elapsed); end
58
+ def hard_timeouts_sec; ratio(hard_timeouts, elapsed); end
59
+ def soft_timeouts_sec; ratio(soft_timeouts, elapsed); end
60
+
61
+ def failure_rate; ratio(all_failures * 100, requests); end
62
+
63
+ def add_from(other)
64
+ @mutex.synchronize do
65
+ @successes += other.successes
66
+ @failures += other.failures
67
+ @hard_timeouts += other.hard_timeouts
68
+ @soft_timeouts += other.soft_timeouts
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def ratio(num, denom)
75
+ return nil unless num && denom && denom > 0
76
+ num / denom.to_f
77
+ end
78
+ end
@@ -0,0 +1,68 @@
1
+ # TODO: Namespacing/classes/etc!
2
+
3
+ # rubocop:disable Lint/RescueException
4
+ def guard_call(prefix, &block)
5
+ block.call
6
+ rescue Exception => e
7
+ SparkleMotion.logger.error { "#{prefix}: Exception for #{prefix}: #{e.message}" }
8
+ SparkleMotion.logger.error { "#{prefix}:\t#{e.backtrace.join("\n#{prefix}:\t")}" }
9
+ end
10
+ # rubocop:enable Lint/RescueException
11
+
12
+ module SparkleMotion
13
+ # Class to represent configurations and positioning of lights.
14
+ class LightConfig
15
+ attr_accessor :bridges, :lights, :masks
16
+
17
+ def initialize(config:, group:)
18
+ group_config = config[group]
19
+ num_lights = group_config.length
20
+
21
+ lights_by_bridge = group_lights_by_bridge(group_config)
22
+
23
+ index = 0
24
+ masks_by_bridge = {}
25
+ lights_by_bridge.each do |(bridge_name, lights)|
26
+ lights_by_bridge[bridge_name], index = index_lights(lights, index)
27
+ masks_by_bridge[bridge_name] = mask_lights(lights_by_bridge[bridge_name], num_lights)
28
+ end
29
+
30
+ set_state!(config, lights_by_bridge, masks_by_bridge)
31
+ end
32
+
33
+ protected
34
+
35
+ def set_state!(config, lights, masks)
36
+ @bridges = config["bridges"]
37
+ @lights = lights
38
+ @masks = masks
39
+ end
40
+
41
+ def group_lights_by_bridge(config)
42
+ groups = Hash.new { |hsh, x| hsh[x] = [] }
43
+ config.each do |(bridge_name, light_id)|
44
+ groups[bridge_name] << light_id
45
+ end
46
+ groups
47
+ end
48
+
49
+ # Determine globally unique index for each light, so we can address them
50
+ # logically, but also relate physical mappings.
51
+ def index_lights(lights, index)
52
+ indexed_lights = []
53
+ lights.each do |light_id|
54
+ indexed_lights << [index, light_id]
55
+ index += 1
56
+ end
57
+ [indexed_lights, index]
58
+ end
59
+
60
+ # Create a mask for the global set of lights to easily tell which ones
61
+ # belong to a given bridge.
62
+ def mask_lights(indexed_lights, length)
63
+ mask = [false] * length
64
+ indexed_lights.map(&:first).each { |idx| mask[idx] = true }
65
+ mask
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,11 @@
1
+ # TODO: Namespacing!
2
+ # A 2-component vector, where components go from 0.0..1.0.
3
+ class Vector2
4
+ attr_reader :x, :y
5
+ def initialize(x: 0.0, y: 0.0)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def to_s; "<<#{@x}, #{@y}>>"; end
11
+ end
@@ -0,0 +1,3 @@
1
+ module SparkleMotion
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
+ require "sparkle_motion/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sparkle_motion"
7
+ s.version = SparkleMotion::VERSION
8
+ s.author = "Jon Frisby"
9
+ s.email = "jfrisby@mrjoy.com"
10
+ s.homepage = "http://github.com/MrJoy/sparkle_motion"
11
+ s.description = "A system for generative event lighting using Philips Hue controlled"\
12
+ " from a Novation Launchpad"
13
+ s.summary = "Generative event lighting using Philips Hue, and Novation Launchpad"
14
+ raw_file_list = `git ls-files`.split("\n")
15
+ s.files = raw_file_list
16
+ .reject do |fname|
17
+ fname =~ %r{
18
+ \A
19
+ (\..*
20
+ |Gemfile.*
21
+ |notes/.*
22
+ |tasks/.*
23
+ |tools/.*
24
+ |examples/.*
25
+ |tmp/.*
26
+ |Rakefile
27
+ |.*\.sublime-project
28
+ )
29
+ \z
30
+ }x
31
+ end
32
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
33
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
34
+ s.extra_rdoc_files = %w(CHANGELOG.md README.md LICENSE)
35
+ s.require_paths = ["lib"]
36
+ s.required_ruby_version = Gem::Requirement.new(">= 2.2.0")
37
+
38
+ s.add_dependency "oj", "~> 2.12.13"
39
+ s.add_dependency "curb", "~> 0.8.8"
40
+ s.add_dependency "perlin_noise", "~> 0.1.2"
41
+ s.add_dependency "logger-better", "~> 0.2.1"
42
+ s.add_dependency "frisky"
43
+ s.add_dependency "mrjoy-launchpad"
44
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sparkle_motion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Frisby
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.12.13
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.12.13
27
+ - !ruby/object:Gem::Dependency
28
+ name: curb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.8
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.8
41
+ - !ruby/object:Gem::Dependency
42
+ name: perlin_noise
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: logger-better
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: frisky
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mrjoy-launchpad
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: A system for generative event lighting using Philips Hue controlled from
98
+ a Novation Launchpad
99
+ email: jfrisby@mrjoy.com
100
+ executables:
101
+ - sm-discover
102
+ - sm-mark-lights
103
+ - sm-off
104
+ - sm-on
105
+ - sm-simulate
106
+ - sm-watch-memory
107
+ - sparkle-motion
108
+ extensions: []
109
+ extra_rdoc_files:
110
+ - CHANGELOG.md
111
+ - README.md
112
+ - LICENSE
113
+ files:
114
+ - CHANGELOG.md
115
+ - LICENSE
116
+ - README.md
117
+ - bin/sm-discover
118
+ - bin/sm-mark-lights
119
+ - bin/sm-off
120
+ - bin/sm-on
121
+ - bin/sm-simulate
122
+ - bin/sm-watch-memory
123
+ - bin/sparkle-motion
124
+ - config.yml
125
+ - data/dynamic/bridges.csv
126
+ - data/static/devices.csv
127
+ - lib/sparkle_motion.rb
128
+ - lib/sparkle_motion/config.rb
129
+ - lib/sparkle_motion/env.rb
130
+ - lib/sparkle_motion/http.rb
131
+ - lib/sparkle_motion/hue/ssdp.rb
132
+ - lib/sparkle_motion/launch_pad/color.rb
133
+ - lib/sparkle_motion/launch_pad/widget.rb
134
+ - lib/sparkle_motion/launch_pad/widgets/button.rb
135
+ - lib/sparkle_motion/launch_pad/widgets/horizontal_slider.rb
136
+ - lib/sparkle_motion/launch_pad/widgets/radio_group.rb
137
+ - lib/sparkle_motion/launch_pad/widgets/toggle.rb
138
+ - lib/sparkle_motion/launch_pad/widgets/vertical_slider.rb
139
+ - lib/sparkle_motion/lazy_request_config.rb
140
+ - lib/sparkle_motion/node.rb
141
+ - lib/sparkle_motion/nodes/generator.rb
142
+ - lib/sparkle_motion/nodes/generators/const.rb
143
+ - lib/sparkle_motion/nodes/generators/perlin.rb
144
+ - lib/sparkle_motion/nodes/generators/wave2.rb
145
+ - lib/sparkle_motion/nodes/transform.rb
146
+ - lib/sparkle_motion/nodes/transforms/contrast.rb
147
+ - lib/sparkle_motion/nodes/transforms/range.rb
148
+ - lib/sparkle_motion/nodes/transforms/spotlight.rb
149
+ - lib/sparkle_motion/output.rb
150
+ - lib/sparkle_motion/results.rb
151
+ - lib/sparkle_motion/utility.rb
152
+ - lib/sparkle_motion/vector2.rb
153
+ - lib/sparkle_motion/version.rb
154
+ - sparkle_motion.gemspec
155
+ homepage: http://github.com/MrJoy/sparkle_motion
156
+ licenses: []
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 2.2.0
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.4.5.1
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Generative event lighting using Philips Hue, and Novation Launchpad
178
+ test_files: []