bubble-wrap 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +1 -1
- data/GETTING_STARTED.md +1 -1
- data/Gemfile.lock +10 -10
- data/README.md +266 -122
- data/Rakefile +1 -1
- data/bubble-wrap.gemspec +7 -6
- data/lib/bubble-wrap.rb +0 -1
- data/lib/bubble-wrap/all.rb +13 -1
- data/lib/bubble-wrap/location.rb +1 -1
- data/lib/bubble-wrap/motion.rb +10 -0
- data/lib/bubble-wrap/rss_parser.rb +0 -1
- data/lib/bubble-wrap/test.rb +1 -0
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core/device/ios/camera.rb +12 -1
- data/motion/core/ios/device.rb +7 -1
- data/motion/core/json.rb +1 -1
- data/motion/core/osx/app.rb +11 -1
- data/motion/core/time.rb +27 -4
- data/motion/location/location.rb +6 -2
- data/motion/mail/mail.rb +4 -0
- data/motion/media/player.rb +2 -1
- data/motion/motion/motion.rb +421 -0
- data/motion/reactor/deferrable.rb +29 -3
- data/motion/reactor/eventable.rb +3 -1
- data/motion/reactor/thread_aware_deferrable.rb +37 -0
- data/motion/rss_parser.rb +11 -21
- data/motion/sms/sms.rb +4 -0
- data/motion/ui/ui_alert_view.rb +3 -1
- data/motion/ui/ui_control_wrapper.rb +27 -0
- data/motion/ui/ui_view_wrapper.rb +1 -7
- data/motion/util/constants.rb +1 -1
- data/samples/alert/Gemfile +1 -0
- data/samples/alert/Gemfile.lock +16 -0
- data/samples/alert/Rakefile +1 -1
- data/samples/camera/Gemfile +2 -1
- data/samples/camera/Gemfile.lock +16 -0
- data/samples/camera/Rakefile +1 -1
- data/samples/gesture/Gemfile +2 -1
- data/samples/gesture/Gemfile.lock +9 -3
- data/samples/gesture/Rakefile +1 -1
- data/samples/location/Gemfile +3 -1
- data/samples/location/Gemfile.lock +18 -0
- data/samples/location/Rakefile +4 -2
- data/samples/location/app/controllers/{image_list_controller.rb → places_list_controller.rb} +0 -0
- data/samples/media/Gemfile +4 -0
- data/samples/media/Gemfile.lock +16 -0
- data/samples/media/Rakefile +1 -1
- data/samples/osx/Gemfile +3 -1
- data/samples/osx/Gemfile.lock +5 -1
- data/spec/lib/bubble-wrap/requirement_spec.rb +2 -2
- data/spec/motion/core/app_spec.rb +23 -0
- data/spec/motion/core/device/ios/camera_spec.rb +1 -1
- data/spec/motion/core/device/ios/device_spec.rb +6 -0
- data/spec/motion/core/ios/app_spec.rb +9 -24
- data/spec/motion/core/json_spec.rb +30 -10
- data/spec/motion/core/osx/app_spec.rb +2 -1
- data/spec/motion/core/time_spec.rb +34 -1
- data/spec/motion/location/location_spec.rb +6 -0
- data/spec/motion/mail/mail_spec.rb +20 -16
- data/spec/motion/motion/core_motion_spec.rb +231 -0
- data/spec/motion/reactor/deferrable_spec.rb +81 -0
- data/spec/motion/reactor/eventable_spec.rb +11 -0
- data/spec/motion/reactor/thread_aware_deferrable_spec.rb +85 -0
- data/spec/motion/rss_parser_spec.rb +11 -21
- data/spec/motion/sms/sms_spec.rb +11 -6
- data/spec/motion/ui/ui_alert_view_spec.rb +23 -0
- data/spec/motion/ui/ui_control_wrapper_spec.rb +24 -0
- metadata +58 -38
- data/lib/bubble-wrap/http.rb +0 -7
data/Rakefile
CHANGED
@@ -28,7 +28,7 @@ Motion::Project::App.setup do |app|
|
|
28
28
|
app.spec_files
|
29
29
|
if Motion::Project::App.osx?
|
30
30
|
app.spec_files -= Dir.glob("./spec/motion/**/ios/**.rb")
|
31
|
-
["font", "location", "media", "ui", "mail", "sms", "network-indicator"].each do |package|
|
31
|
+
["font", "motion", "location", "media", "ui", "mail", "sms", "network-indicator"].each do |package|
|
32
32
|
app.spec_files -= Dir.glob("./spec/motion/#{package}/**/*.rb")
|
33
33
|
end
|
34
34
|
else
|
data/bubble-wrap.gemspec
CHANGED
@@ -3,10 +3,11 @@ require File.expand_path('../lib/bubble-wrap/version', __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ['Matt Aimonetti', 'Francis Chong', 'James Harton', 'Clay Allsopp', 'Dylan Markow', 'Jan Weinkauff', 'Marin Usalj']
|
6
|
-
gem.email = ['mattaimonetti@gmail.com', 'francis@ignition.hk', 'james@sociable.co.nz', 'clay.allsopp@gmail.com', 'dylan@dylanmarkow.com', 'jan@dreimannzelt.de', '
|
6
|
+
gem.email = ['mattaimonetti@gmail.com', 'francis@ignition.hk', 'james@sociable.co.nz', 'clay.allsopp@gmail.com', 'dylan@dylanmarkow.com', 'jan@dreimannzelt.de', 'marin2211@gmail.com']
|
7
7
|
gem.description = 'RubyMotion wrappers and helpers (Ruby for iOS and OS X) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request.'
|
8
8
|
gem.summary = 'RubyMotion wrappers and helpers (Ruby for iOS and OS X) - Making Cocoa APIs more Ruby like, one API at a time. Fork away and send your pull request.'
|
9
9
|
gem.homepage = 'http://rubymotion.github.io/BubbleWrap/'
|
10
|
+
gem.license = 'MIT'
|
10
11
|
|
11
12
|
gem.files = `git ls-files`.split($\)
|
12
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|lib_spec|features)/})
|
@@ -16,9 +17,9 @@ Gem::Specification.new do |gem|
|
|
16
17
|
|
17
18
|
gem.extra_rdoc_files = gem.files.grep(%r{motion})
|
18
19
|
|
19
|
-
gem.
|
20
|
-
gem.add_development_dependency 'mocha', '0.
|
21
|
-
gem.add_development_dependency '
|
22
|
-
gem.add_development_dependency '
|
23
|
-
gem.add_development_dependency '
|
20
|
+
gem.add_development_dependency 'mocha', '~> 0.11'
|
21
|
+
gem.add_development_dependency 'mocha-on-bacon', '~> 0.2'
|
22
|
+
gem.add_development_dependency 'bacon', '~> 1.2'
|
23
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
gem.add_development_dependency 'webstub', '~> 1.1'
|
24
25
|
end
|
data/lib/bubble-wrap.rb
CHANGED
data/lib/bubble-wrap/all.rb
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
require File.expand_path('../loader', __FILE__)
|
2
|
-
[
|
2
|
+
[
|
3
|
+
'core',
|
4
|
+
'font',
|
5
|
+
'location',
|
6
|
+
'mail',
|
7
|
+
'media',
|
8
|
+
'motion',
|
9
|
+
'network-indicator',
|
10
|
+
'reactor',
|
11
|
+
'rss_parser',
|
12
|
+
'sms',
|
13
|
+
'ui',
|
14
|
+
].each { |sub|
|
3
15
|
require File.expand_path("../#{sub}", __FILE__)
|
4
16
|
}
|
data/lib/bubble-wrap/location.rb
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'bubble-wrap/loader'
|
2
|
+
|
3
|
+
BubbleWrap.require_ios('motion') do
|
4
|
+
BubbleWrap.require('motion/util/constants.rb')
|
5
|
+
BubbleWrap.require('motion/core/string.rb')
|
6
|
+
BubbleWrap.require('motion/motion/**/*.rb') do
|
7
|
+
file('motion/motion/motion.rb').depends_on 'motion/util/constants.rb'
|
8
|
+
file('motion/motion/motion.rb').uses_framework('CoreMotion')
|
9
|
+
end
|
10
|
+
end
|
data/lib/bubble-wrap/test.rb
CHANGED
data/lib/bubble-wrap/version.rb
CHANGED
@@ -15,6 +15,13 @@ module BubbleWrap
|
|
15
15
|
Constants.register UIImagePickerControllerSourceTypePhotoLibrary, UIImagePickerControllerSourceTypeCamera,
|
16
16
|
UIImagePickerControllerSourceTypeSavedPhotosAlbum
|
17
17
|
|
18
|
+
Constants.register UIImagePickerControllerQualityTypeHigh,
|
19
|
+
UIImagePickerControllerQualityTypeMedium,
|
20
|
+
UIImagePickerControllerQualityTypeLow,
|
21
|
+
UIImagePickerControllerQualityType640x480,
|
22
|
+
UIImagePickerControllerQualityTypeIFrame1280x720,
|
23
|
+
UIImagePickerControllerQualityTypeIFrame960x540
|
24
|
+
|
18
25
|
MEDIA_TYPE_HASH = {movie: KUTTypeMovie, image: KUTTypeImage}
|
19
26
|
|
20
27
|
CAMERA_LOCATIONS = [:front, :rear, :none]
|
@@ -98,7 +105,9 @@ module BubbleWrap
|
|
98
105
|
animated: true,
|
99
106
|
on_dismiss: false,
|
100
107
|
media_types: [:image],
|
101
|
-
dismiss_completed: nil
|
108
|
+
dismiss_completed: nil,
|
109
|
+
video_quality: :medium,
|
110
|
+
video_maximum_duration: 600
|
102
111
|
}.merge(options)
|
103
112
|
|
104
113
|
# If we're using Camera.any, by default use photo library
|
@@ -130,6 +139,8 @@ module BubbleWrap
|
|
130
139
|
self.picker.sourceType = source_type
|
131
140
|
self.picker.mediaTypes = media_types
|
132
141
|
self.picker.allowsEditing = @options[:allows_editing]
|
142
|
+
self.picker.videoQuality = Constants.get("UIImagePickerControllerQualityType", @options[:video_quality])
|
143
|
+
self.picker.videoMaximumDuration = @options[:video_maximum_duration]
|
133
144
|
|
134
145
|
if source_type_readable == :camera && ![:front, :rear].member?(self.location)
|
135
146
|
raise Error::INVALID_CAMERA_LOCATION, "Can't use camera location #{self.location} with source type :camera"
|
data/motion/core/ios/device.rb
CHANGED
@@ -51,6 +51,12 @@ module BubbleWrap
|
|
51
51
|
UIDevice.currentDevice.systemVersion
|
52
52
|
end
|
53
53
|
|
54
|
+
# Returns an identifier unique to the vendor across the vendors app.
|
55
|
+
# @return [NSUUID]
|
56
|
+
def vendor_identifier
|
57
|
+
UIDevice.currentDevice.identifierForVendor
|
58
|
+
end
|
59
|
+
|
54
60
|
# Delegates to BubbleWrap::Screen.orientation
|
55
61
|
def orientation
|
56
62
|
screen.orientation
|
@@ -61,4 +67,4 @@ module BubbleWrap
|
|
61
67
|
screen.interface_orientation
|
62
68
|
end
|
63
69
|
end
|
64
|
-
end
|
70
|
+
end
|
data/motion/core/json.rb
CHANGED
@@ -14,7 +14,7 @@ module BubbleWrap
|
|
14
14
|
# TODO: support options like the C Ruby module does
|
15
15
|
def self.parse(str_data, &block)
|
16
16
|
return nil unless str_data
|
17
|
-
data = str_data.respond_to?(:
|
17
|
+
data = str_data.respond_to?('dataUsingEncoding:') ? str_data.dataUsingEncoding(NSUTF8StringEncoding) : str_data
|
18
18
|
opts = NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves | NSJSONReadingAllowFragments
|
19
19
|
error = Pointer.new(:id)
|
20
20
|
obj = NSJSONSerialization.JSONObjectWithData(data, options:opts, error:error)
|
data/motion/core/osx/app.rb
CHANGED
@@ -2,6 +2,15 @@ module BubbleWrap
|
|
2
2
|
module App
|
3
3
|
module_function
|
4
4
|
|
5
|
+
# Opens an url (string or instance of `NSURL`)
|
6
|
+
# in the default web browser
|
7
|
+
# Usage Example:
|
8
|
+
# App.open_url("http://www.rubymotion.com")
|
9
|
+
def open_url(url)
|
10
|
+
url = NSURL.URLWithString(url) unless url.is_a?(NSURL)
|
11
|
+
NSWorkspace.sharedWorkspace.openURL(url)
|
12
|
+
end
|
13
|
+
|
5
14
|
# Application Delegate
|
6
15
|
def delegate
|
7
16
|
shared.delegate
|
@@ -11,5 +20,6 @@ module BubbleWrap
|
|
11
20
|
def shared
|
12
21
|
NSApplication.sharedApplication
|
13
22
|
end
|
23
|
+
|
14
24
|
end
|
15
|
-
end
|
25
|
+
end
|
data/motion/core/time.rb
CHANGED
@@ -1,25 +1,48 @@
|
|
1
1
|
class Time
|
2
|
-
|
2
|
+
|
3
3
|
def self.iso8601(time)
|
4
|
+
if time.include?(".")
|
5
|
+
# Fractional Seconds
|
6
|
+
if time.include?('Z')
|
7
|
+
iso8601_with_fractional_seconds(time)
|
8
|
+
else
|
9
|
+
iso8601_with_fractional_seconds_and_timesone(time)
|
10
|
+
end
|
11
|
+
else
|
12
|
+
# Non Fractional Seconds
|
13
|
+
if time.include?('Z')
|
14
|
+
iso8601_zulu(time)
|
15
|
+
else
|
16
|
+
iso8601_with_timezone(time)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.iso8601_zulu(time)
|
4
22
|
cached_date_formatter("yyyy-MM-dd'T'HH:mm:ss'Z'").
|
5
23
|
dateFromString(time)
|
6
24
|
end
|
7
|
-
|
25
|
+
|
8
26
|
def self.iso8601_with_timezone(time)
|
9
27
|
cached_date_formatter("yyyy-MM-dd'T'HH:mm:ssZZZZZ").
|
10
28
|
dateFromString(time)
|
11
29
|
end
|
12
|
-
|
30
|
+
|
13
31
|
def self.iso8601_with_fractional_seconds(time)
|
14
32
|
cached_date_formatter("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").
|
15
33
|
dateFromString(time)
|
16
34
|
end
|
17
35
|
|
36
|
+
def self.iso8601_with_fractional_seconds_and_timesone(time)
|
37
|
+
cached_date_formatter("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ").
|
38
|
+
dateFromString(time)
|
39
|
+
end
|
40
|
+
|
18
41
|
private
|
19
42
|
|
20
43
|
def self.cached_date_formatter(dateFormat)
|
21
44
|
Thread.current[:date_formatters] ||= {}
|
22
|
-
Thread.current[:date_formatters][dateFormat] ||=
|
45
|
+
Thread.current[:date_formatters][dateFormat] ||=
|
23
46
|
NSDateFormatter.alloc.init.tap do |formatter|
|
24
47
|
formatter.dateFormat = dateFormat
|
25
48
|
formatter.timeZone = NSTimeZone.timeZoneWithAbbreviation "UTC"
|
data/motion/location/location.rb
CHANGED
@@ -25,6 +25,10 @@ module BubbleWrap
|
|
25
25
|
KCLLocationAccuracyNearestTenMeters, KCLLocationAccuracyHundredMeters,
|
26
26
|
KCLLocationAccuracyKilometer, KCLLocationAccuracyThreeKilometers
|
27
27
|
|
28
|
+
# New additions to CLAuthorizationStatus in ios8
|
29
|
+
# see: https://developer.apple.com/library/prerelease/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/c/tdef/CLAuthorizationStatus
|
30
|
+
Constants.register KCLAuthorizationStatusAuthorizedWhenInUse, KCLAuthorizationStatusAuthorizedAlways
|
31
|
+
|
28
32
|
module_function
|
29
33
|
# Start getting locations
|
30
34
|
# @param [Hash] options = {
|
@@ -150,14 +154,14 @@ module BubbleWrap
|
|
150
154
|
@location_manager
|
151
155
|
end
|
152
156
|
|
153
|
-
# returns true/false whether services are enabled for the _device_
|
157
|
+
# returns true/false whether services, or limited services, are enabled for the _device_
|
154
158
|
def enabled?
|
155
159
|
CLLocationManager.locationServicesEnabled
|
156
160
|
end
|
157
161
|
|
158
162
|
# returns true/false whether services are enabled for the _app_
|
159
163
|
def authorized?
|
160
|
-
CLLocationManager.authorizationStatus
|
164
|
+
[KCLAuthorizationStatusAuthorized, KCLAuthorizationStatusAuthorizedAlways, KCLAuthorizationStatusAuthorizedWhenInUse].include?(CLLocationManager.authorizationStatus)
|
161
165
|
end
|
162
166
|
|
163
167
|
def error(type)
|
data/motion/mail/mail.rb
CHANGED
@@ -56,6 +56,10 @@ module BubbleWrap
|
|
56
56
|
mail_controller
|
57
57
|
end
|
58
58
|
|
59
|
+
def can_send_mail?
|
60
|
+
!!MFMailComposeViewController.canSendMail
|
61
|
+
end
|
62
|
+
|
59
63
|
# Event when the MFMailComposeViewController is closed
|
60
64
|
# -------------------------------------------------------------
|
61
65
|
# the callback is fired if it was present in the constructor
|
data/motion/media/player.rb
CHANGED
@@ -73,11 +73,12 @@ module BubbleWrap
|
|
73
73
|
klass = display_modal ? MPMoviePlayerViewController : MPMoviePlayerController
|
74
74
|
|
75
75
|
content_url = content_url.is_a?(NSURL) ? content_url : NSURL.URLWithString(content_url)
|
76
|
-
@media_player = klass.alloc.
|
76
|
+
@media_player = klass.alloc.init
|
77
77
|
|
78
78
|
self.media_player.prepareToPlay if not display_modal
|
79
79
|
|
80
80
|
set_player_options(options)
|
81
|
+
self.media_player.setContentURL(content_url)
|
81
82
|
|
82
83
|
NSNotificationCenter.defaultCenter.observe MPMoviePlayerPlaybackDidFinishNotification do |notification|
|
83
84
|
h = notification.userInfo
|
@@ -0,0 +1,421 @@
|
|
1
|
+
# Provides a nice DSL for interacting with the standard CMMotionManager from
|
2
|
+
# CoreMotion
|
3
|
+
module BubbleWrap
|
4
|
+
# These module methods provide the main interface. It uses a shared manager
|
5
|
+
# (per Apple's recommendation), and they all have a common set of supported
|
6
|
+
# methods:
|
7
|
+
# available?
|
8
|
+
# active?
|
9
|
+
# repeat(opts)
|
10
|
+
# once(opts)
|
11
|
+
# every(time_interval, opts)
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# if BW::Motion.accelerometer.available?
|
15
|
+
# BW::Motion.accelerometer.every(5) do |result|
|
16
|
+
# # see the README for the keys that are available in result.
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# If you insist on using your own manager, or you want more than one
|
21
|
+
# BW::Motion::Whatever running at the same time, you'll need to instantiate
|
22
|
+
# them yourself.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# mgr = CMMotionManager.alloc.init
|
26
|
+
# accel = BW::Motion::Accelerometer.new(mgr)
|
27
|
+
# accel.once do |result_data|
|
28
|
+
# end
|
29
|
+
# # => BW::Motion::accelerometer.once do |result_data| ... end
|
30
|
+
module Motion
|
31
|
+
module_function
|
32
|
+
|
33
|
+
def manager
|
34
|
+
@manager ||= CMMotionManager.alloc.init
|
35
|
+
end
|
36
|
+
|
37
|
+
def accelerometer
|
38
|
+
@accelerometer ||= Accelerometer.new(self.manager)
|
39
|
+
end
|
40
|
+
|
41
|
+
def gyroscope
|
42
|
+
@gyroscope ||= Gyroscope.new(self.manager)
|
43
|
+
end
|
44
|
+
|
45
|
+
def magnetometer
|
46
|
+
@magnetometer ||= Magnetometer.new(self.manager)
|
47
|
+
end
|
48
|
+
|
49
|
+
def device
|
50
|
+
@device ||= DeviceMotion.new(self.manager)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
module Motion
|
56
|
+
module Error
|
57
|
+
end
|
58
|
+
|
59
|
+
class GenericMotionInterface
|
60
|
+
|
61
|
+
def initialize(manager)
|
62
|
+
@manager = manager
|
63
|
+
end
|
64
|
+
|
65
|
+
def repeat(options={}, &blk)
|
66
|
+
raise "A block is required" unless blk
|
67
|
+
blk.weak! if BubbleWrap.use_weak_callbacks?
|
68
|
+
|
69
|
+
self.start(options, &blk)
|
70
|
+
return self
|
71
|
+
end
|
72
|
+
|
73
|
+
def every(time=nil, options={}, &blk)
|
74
|
+
raise "A block is required" unless blk
|
75
|
+
blk.weak! if BubbleWrap.use_weak_callbacks?
|
76
|
+
|
77
|
+
if time.is_a?(NSDictionary)
|
78
|
+
options = time
|
79
|
+
elsif time
|
80
|
+
options = options.merge(interval: time)
|
81
|
+
end
|
82
|
+
|
83
|
+
self.start(options, &blk)
|
84
|
+
return self
|
85
|
+
end
|
86
|
+
|
87
|
+
def once(options={}, &blk)
|
88
|
+
raise "A block is required" unless blk
|
89
|
+
blk.weak! if BubbleWrap.use_weak_callbacks?
|
90
|
+
|
91
|
+
@called_once = false
|
92
|
+
every(options) do |result, error|
|
93
|
+
unless @called_once
|
94
|
+
@called_once = true
|
95
|
+
blk.call(result, error)
|
96
|
+
end
|
97
|
+
self.stop
|
98
|
+
end
|
99
|
+
|
100
|
+
return self
|
101
|
+
end
|
102
|
+
|
103
|
+
private def convert_queue(queue_name)
|
104
|
+
case queue_name
|
105
|
+
when :main, nil
|
106
|
+
return NSOperationQueue.mainQueue
|
107
|
+
when :background
|
108
|
+
queue = NSOperationQueue.new
|
109
|
+
queue.name = 'com.bubble-wrap.core-motion.background-queue'
|
110
|
+
return queue
|
111
|
+
when :current
|
112
|
+
return NSOperationQueue.currentQueue
|
113
|
+
when String
|
114
|
+
queue = NSOperationQueue.new
|
115
|
+
queue.name = queue_name
|
116
|
+
return queue
|
117
|
+
else
|
118
|
+
queue_name
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private def internal_handler(handler)
|
123
|
+
retval = -> (result_data, error) do
|
124
|
+
handle_result(result_data, error, handler)
|
125
|
+
end
|
126
|
+
retval.weak! if BubbleWrap.use_weak_callbacks?
|
127
|
+
retval
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
class Accelerometer < GenericMotionInterface
|
133
|
+
|
134
|
+
def start(options={}, &handler)
|
135
|
+
if options.key?(:interval)
|
136
|
+
@manager.accelerometerUpdateInterval = options[:interval]
|
137
|
+
end
|
138
|
+
|
139
|
+
if handler
|
140
|
+
queue = convert_queue(options[:queue])
|
141
|
+
@manager.startAccelerometerUpdatesToQueue(queue, withHandler: internal_handler(handler))
|
142
|
+
else
|
143
|
+
@manager.startAccelerometerUpdates
|
144
|
+
end
|
145
|
+
|
146
|
+
return self
|
147
|
+
end
|
148
|
+
|
149
|
+
private def handle_result(result_data, error, handler)
|
150
|
+
if result_data
|
151
|
+
result = {
|
152
|
+
data: result_data,
|
153
|
+
acceleration: result_data.acceleration,
|
154
|
+
x: result_data.acceleration.x,
|
155
|
+
y: result_data.acceleration.y,
|
156
|
+
z: result_data.acceleration.z,
|
157
|
+
}
|
158
|
+
else
|
159
|
+
result = nil
|
160
|
+
end
|
161
|
+
|
162
|
+
handler.call(result, error)
|
163
|
+
end
|
164
|
+
|
165
|
+
def available?
|
166
|
+
@manager.accelerometerAvailable?
|
167
|
+
end
|
168
|
+
|
169
|
+
def active?
|
170
|
+
@manager.accelerometerActive?
|
171
|
+
end
|
172
|
+
|
173
|
+
def data
|
174
|
+
@manager.accelerometerData
|
175
|
+
end
|
176
|
+
|
177
|
+
def stop
|
178
|
+
@manager.stopAccelerometerUpdates
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
class Gyroscope < GenericMotionInterface
|
184
|
+
|
185
|
+
def start(options={}, &handler)
|
186
|
+
if options.key?(:interval)
|
187
|
+
@manager.gyroUpdateInterval = options[:interval]
|
188
|
+
end
|
189
|
+
|
190
|
+
if handler
|
191
|
+
queue = convert_queue(options[:queue])
|
192
|
+
@manager.startGyroUpdatesToQueue(queue, withHandler: internal_handler(handler))
|
193
|
+
else
|
194
|
+
@manager.startGyroUpdates
|
195
|
+
end
|
196
|
+
|
197
|
+
return self
|
198
|
+
end
|
199
|
+
|
200
|
+
private def handle_result(result_data, error, handler)
|
201
|
+
if result_data
|
202
|
+
result = {
|
203
|
+
data: result_data,
|
204
|
+
rotation: result_data.rotationRate,
|
205
|
+
x: result_data.rotationRate.x,
|
206
|
+
y: result_data.rotationRate.y,
|
207
|
+
z: result_data.rotationRate.z,
|
208
|
+
}
|
209
|
+
else
|
210
|
+
result = nil
|
211
|
+
end
|
212
|
+
|
213
|
+
handler.call(result, error)
|
214
|
+
end
|
215
|
+
|
216
|
+
def available?
|
217
|
+
@manager.gyroAvailable?
|
218
|
+
end
|
219
|
+
|
220
|
+
def active?
|
221
|
+
@manager.gyroActive?
|
222
|
+
end
|
223
|
+
|
224
|
+
def data
|
225
|
+
@manager.gyroData
|
226
|
+
end
|
227
|
+
|
228
|
+
def stop
|
229
|
+
@manager.stopGyroUpdates
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
class Magnetometer < GenericMotionInterface
|
235
|
+
|
236
|
+
def start(options={}, &handler)
|
237
|
+
if options.key?(:interval)
|
238
|
+
@manager.magnetometerUpdateInterval = options[:interval]
|
239
|
+
end
|
240
|
+
|
241
|
+
if handler
|
242
|
+
queue = convert_queue(options[:queue])
|
243
|
+
@manager.startMagnetometerUpdatesToQueue(queue, withHandler: internal_handler(handler))
|
244
|
+
else
|
245
|
+
@manager.startMagnetometerUpdates
|
246
|
+
end
|
247
|
+
|
248
|
+
return self
|
249
|
+
end
|
250
|
+
|
251
|
+
private def handle_result(result_data, error, handler)
|
252
|
+
if result_data
|
253
|
+
result = {
|
254
|
+
data: result_data,
|
255
|
+
field: result_data.magneticField,
|
256
|
+
x: result_data.magneticField.x,
|
257
|
+
y: result_data.magneticField.y,
|
258
|
+
z: result_data.magneticField.z,
|
259
|
+
}
|
260
|
+
else
|
261
|
+
result = nil
|
262
|
+
end
|
263
|
+
|
264
|
+
handler.call(result, error)
|
265
|
+
end
|
266
|
+
|
267
|
+
def available?
|
268
|
+
@manager.magnetometerAvailable?
|
269
|
+
end
|
270
|
+
|
271
|
+
def active?
|
272
|
+
@manager.magnetometerActive?
|
273
|
+
end
|
274
|
+
|
275
|
+
def data
|
276
|
+
@manager.magnetometerData
|
277
|
+
end
|
278
|
+
|
279
|
+
def stop
|
280
|
+
@manager.stopMagnetometerUpdates
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
class DeviceMotion < GenericMotionInterface
|
286
|
+
|
287
|
+
def start(options={}, &handler)
|
288
|
+
if options.key?(:interval)
|
289
|
+
@manager.deviceMotionUpdateInterval = options[:interval]
|
290
|
+
end
|
291
|
+
|
292
|
+
if options.key?(:reference)
|
293
|
+
reference_frame = convert_reference_frame(options[:reference])
|
294
|
+
else
|
295
|
+
reference_frame = nil
|
296
|
+
end
|
297
|
+
|
298
|
+
if handler
|
299
|
+
queue = convert_queue(options[:queue])
|
300
|
+
|
301
|
+
if reference_frame
|
302
|
+
@manager.startDeviceMotionUpdatesUsingReferenceFrame(reference_frame, toQueue: queue, withHandler: internal_handler(handler))
|
303
|
+
else
|
304
|
+
@manager.startDeviceMotionUpdatesToQueue(queue, withHandler: internal_handler(handler))
|
305
|
+
end
|
306
|
+
else
|
307
|
+
if reference_frame
|
308
|
+
@manager.startDeviceMotionUpdatesUsingReferenceFrame(reference_frame)
|
309
|
+
else
|
310
|
+
@manager.startDeviceMotionUpdates
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
return self
|
315
|
+
end
|
316
|
+
|
317
|
+
private def handle_result(result_data, error, handler)
|
318
|
+
if result_data
|
319
|
+
result = {
|
320
|
+
data: result_data,
|
321
|
+
attitude: result_data.attitude,
|
322
|
+
rotation: result_data.rotationRate,
|
323
|
+
gravity: result_data.gravity,
|
324
|
+
acceleration: result_data.userAcceleration,
|
325
|
+
magnetic: result_data.magneticField,
|
326
|
+
}
|
327
|
+
|
328
|
+
if result_data.attitude
|
329
|
+
result.merge!({
|
330
|
+
roll: result_data.attitude.roll,
|
331
|
+
pitch: result_data.attitude.pitch,
|
332
|
+
yaw: result_data.attitude.yaw,
|
333
|
+
matrix: result_data.attitude.rotationMatrix,
|
334
|
+
quaternion: result_data.attitude.quaternion,
|
335
|
+
})
|
336
|
+
end
|
337
|
+
|
338
|
+
if result_data.rotationRate
|
339
|
+
result.merge!({
|
340
|
+
rotation_x: result_data.rotationRate.x,
|
341
|
+
rotation_y: result_data.rotationRate.y,
|
342
|
+
rotation_z: result_data.rotationRate.z,
|
343
|
+
})
|
344
|
+
end
|
345
|
+
|
346
|
+
if result_data.gravity
|
347
|
+
result.merge!({
|
348
|
+
gravity_x: result_data.gravity.x,
|
349
|
+
gravity_y: result_data.gravity.y,
|
350
|
+
gravity_z: result_data.gravity.z,
|
351
|
+
})
|
352
|
+
end
|
353
|
+
|
354
|
+
if result_data.userAcceleration
|
355
|
+
result.merge!({
|
356
|
+
acceleration_x: result_data.userAcceleration.x,
|
357
|
+
acceleration_y: result_data.userAcceleration.y,
|
358
|
+
acceleration_z: result_data.userAcceleration.z,
|
359
|
+
})
|
360
|
+
end
|
361
|
+
|
362
|
+
if result_data.magneticField
|
363
|
+
case result_data.magneticField.accuracy
|
364
|
+
when CMMagneticFieldCalibrationAccuracyLow
|
365
|
+
accuracy = :low
|
366
|
+
when CMMagneticFieldCalibrationAccuracyMedium
|
367
|
+
accuracy = :medium
|
368
|
+
when CMMagneticFieldCalibrationAccuracyHigh
|
369
|
+
accuracy = :high
|
370
|
+
end
|
371
|
+
|
372
|
+
result.merge!({
|
373
|
+
field: result_data.magneticField.field,
|
374
|
+
magnetic_x: result_data.magneticField.field.x,
|
375
|
+
magnetic_y: result_data.magneticField.field.y,
|
376
|
+
magnetic_z: result_data.magneticField.field.z,
|
377
|
+
magnetic_accuracy: accuracy,
|
378
|
+
})
|
379
|
+
end
|
380
|
+
else
|
381
|
+
result = nil
|
382
|
+
end
|
383
|
+
|
384
|
+
handler.call(result, error)
|
385
|
+
end
|
386
|
+
|
387
|
+
def convert_reference_frame(reference_frame)
|
388
|
+
case reference_frame
|
389
|
+
when :arbitrary_z
|
390
|
+
CMAttitudeReferenceFrameXArbitraryZVertical
|
391
|
+
when :corrected_z
|
392
|
+
CMAttitudeReferenceFrameXArbitraryCorrectedZVertical
|
393
|
+
when :magnetic_north
|
394
|
+
CMAttitudeReferenceFrameXMagneticNorthZVertical
|
395
|
+
when :true_north
|
396
|
+
CMAttitudeReferenceFrameXTrueNorthZVertical
|
397
|
+
else
|
398
|
+
reference_frame
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def available?
|
403
|
+
@manager.deviceMotionAvailable?
|
404
|
+
end
|
405
|
+
|
406
|
+
def active?
|
407
|
+
@manager.deviceMotionActive?
|
408
|
+
end
|
409
|
+
|
410
|
+
def data
|
411
|
+
@manager.deviceMotion
|
412
|
+
end
|
413
|
+
|
414
|
+
def stop
|
415
|
+
@manager.stopDeviceMotionUpdates
|
416
|
+
end
|
417
|
+
|
418
|
+
end
|
419
|
+
|
420
|
+
end
|
421
|
+
end
|