├── AUTHORS ├── LICENSE ├── README ├── android.c ├── android.go ├── android.h ├── darwin_armx.go ├── darwin_armx.h ├── darwin_armx.m ├── example └── example.go ├── notmobile.go └── sensor.go /AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This package has moved to https://godoc.org/golang.org/x/mobile/exp/sensor. 2 | -------------------------------------------------------------------------------- /android.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build android 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "android.h" 13 | 14 | void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst) { 15 | ASensorManager* manager = ASensorManager_getInstance(); 16 | 17 | ALooper* looper = ALooper_forThread(); 18 | if (looper == NULL) { 19 | looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 20 | } 21 | ASensorEventQueue* queue = ASensorManager_createEventQueue(manager, looper, looperId, NULL, NULL); 22 | dst->looper = looper; 23 | dst->queue = queue; 24 | dst->looperId = looperId; 25 | } 26 | 27 | int GoAndroid_enableSensor(ASensorEventQueue* q, int s, int32_t usec) { 28 | ASensorManager* manager = ASensorManager_getInstance(); 29 | const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); 30 | if (sensor == NULL) { 31 | return 1; 32 | } 33 | ASensorEventQueue_enableSensor(q, sensor); 34 | ASensorEventQueue_setEventRate(q, sensor, usec); 35 | return 0; 36 | } 37 | 38 | void GoAndroid_disableSensor(ASensorEventQueue* q, int s) { 39 | ASensorManager* manager = ASensorManager_getInstance(); 40 | const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s); 41 | ASensorEventQueue_disableSensor(q, sensor); 42 | } 43 | 44 | int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors) { 45 | int id; 46 | int events; 47 | ASensorEvent event; 48 | int i = 0; 49 | // Block for 30 secs at most, timeout if nothing happens. 50 | // Try n times read from the event queue. 51 | // If anytime timeout occurs, don't retry to read and immediately return. 52 | // Consume the event queue entirely between polls. 53 | while (i < n && (id = ALooper_pollAll(30*1000, NULL, &events, NULL)) >= 0) { 54 | if (id != looperId) { 55 | continue; 56 | } 57 | while (i < n && ASensorEventQueue_getEvents(q, &event, 1)) { 58 | types[i] = event.type; 59 | timestamps[i] = event.timestamp; 60 | vectors[i*3] = event.vector.x; 61 | vectors[i*3+1] = event.vector.y; 62 | vectors[i*3+2] = event.vector.z; 63 | i++; 64 | } 65 | } 66 | return i; 67 | } 68 | 69 | void GoAndroid_destroyManager(GoAndroid_SensorManager* m) { 70 | ASensorManager* manager = ASensorManager_getInstance(); 71 | ASensorManager_destroyEventQueue(manager, m->queue); 72 | ALooper_release(m->looper); 73 | } 74 | -------------------------------------------------------------------------------- /android.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build android 6 | 7 | package sensor 8 | 9 | /* 10 | #cgo LDFLAGS: -landroid 11 | 12 | #include 13 | #include 14 | 15 | #include "android.h" 16 | */ 17 | import "C" 18 | import ( 19 | "fmt" 20 | "runtime" 21 | "sync" 22 | "sync/atomic" 23 | "time" 24 | "unsafe" 25 | ) 26 | 27 | var ( 28 | mu sync.Mutex 29 | collecting bool 30 | ) 31 | 32 | var nextLooperID int64 // each underlying ALooper should have a unique ID. 33 | 34 | // initSignal initializes an underlying looper and event queue. 35 | type initSignal struct{} 36 | 37 | // closeSignal destroys the underlying looper and event queue. 38 | type closeSignal struct{} 39 | 40 | // readSignal reads up to len(dst) events and mutates n with 41 | // the number of returned events. If error occurs during the read, 42 | // it mutates err. 43 | type readSignal struct { 44 | dst []Event 45 | n *int 46 | err *error 47 | } 48 | 49 | // enableSignal enables the sensors events on the underlying 50 | // event queue for the specified sensor type with the specified 51 | // latency criterion. 52 | type enableSignal struct { 53 | t Type 54 | delay time.Duration 55 | err *error 56 | } 57 | 58 | // disableSignal disables the events on the underlying event queue 59 | // from the sensor specified. 60 | type disableSignal struct { 61 | t Type 62 | } 63 | 64 | type inOut struct { 65 | in interface{} 66 | out chan struct{} 67 | } 68 | 69 | // manager is the Android-specific implementation of Manager. 70 | type manager struct { 71 | m *C.GoAndroid_SensorManager 72 | inout chan inOut 73 | } 74 | 75 | // initialize inits the manager and creates a goroutine to proxy the CGO calls. 76 | // All actions related to an ALooper needs to be performed from the same 77 | // OS thread. The goroutine proxy locks itself to an OS thread and handles the 78 | // CGO traffic on the same thread. 79 | func (m *manager) initialize() { 80 | m.inout = make(chan inOut) 81 | 82 | go func() { 83 | runtime.LockOSThread() 84 | for { 85 | v := <-m.inout 86 | switch s := v.in.(type) { 87 | case initSignal: 88 | id := atomic.AddInt64(&nextLooperID, int64(1)) 89 | var mgr C.GoAndroid_SensorManager 90 | C.GoAndroid_createManager(C.int(id), &mgr) 91 | m.m = &mgr 92 | case enableSignal: 93 | usecsDelay := s.delay.Nanoseconds() * 1000 94 | code := int(C.GoAndroid_enableSensor(m.m.queue, typeToInt(s.t), C.int32_t(usecsDelay))) 95 | if code != 0 { 96 | *s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t) 97 | } 98 | case disableSignal: 99 | C.GoAndroid_disableSensor(m.m.queue, typeToInt(s.t)) 100 | case readSignal: 101 | n, err := readEvents(m, s.dst) 102 | *s.n = n 103 | *s.err = err 104 | case closeSignal: 105 | C.GoAndroid_destroyManager(m.m) 106 | close(v.out) 107 | return // we don't need this goroutine anymore 108 | } 109 | close(v.out) 110 | } 111 | }() 112 | 113 | if m.m == nil { 114 | done := make(chan struct{}) 115 | m.inout <- inOut{ 116 | in: initSignal{}, 117 | out: done, 118 | } 119 | <-done 120 | } 121 | } 122 | 123 | func (m *manager) enable(s sender, t Type, delay time.Duration) error { 124 | mu.Lock() 125 | if !collecting { 126 | go func() { 127 | ev := make([]Event, 8) 128 | var n int 129 | var err error // TODO(jbd): How to handle the errors? error channel? 130 | for { 131 | done := make(chan struct{}) 132 | m.inout <- inOut{ 133 | in: readSignal{dst: ev, n: &n, err: &err}, 134 | out: done, 135 | } 136 | <-done 137 | for i := 0; i < n; i++ { 138 | s.Send(ev[i]) 139 | } 140 | } 141 | }() 142 | collecting = true 143 | } 144 | mu.Unlock() 145 | 146 | var err error 147 | done := make(chan struct{}) 148 | m.inout <- inOut{ 149 | in: enableSignal{t: t, delay: delay, err: &err}, 150 | out: done, 151 | } 152 | <-done 153 | return err 154 | } 155 | 156 | func (m *manager) disable(t Type) error { 157 | done := make(chan struct{}) 158 | m.inout <- inOut{ 159 | in: disableSignal{t: t}, 160 | out: done, 161 | } 162 | <-done 163 | return nil 164 | } 165 | 166 | func readEvents(m *manager, e []Event) (n int, err error) { 167 | num := len(e) 168 | types := make([]C.int32_t, num) 169 | timestamps := make([]C.int64_t, num) 170 | vectors := make([]C.float, 3*num) 171 | 172 | n = int(C.GoAndroid_readQueue( 173 | m.m.looperId, m.m.queue, 174 | C.int(num), 175 | (*C.int32_t)(unsafe.Pointer(&types[0])), 176 | (*C.int64_t)(unsafe.Pointer(×tamps[0])), 177 | (*C.float)(unsafe.Pointer(&vectors[0]))), 178 | ) 179 | for i := 0; i < n; i++ { 180 | e[i] = Event{ 181 | Sensor: intToType[int(types[i])], 182 | Timestamp: int64(timestamps[i]), 183 | Data: []float64{ 184 | float64(vectors[i*3]), 185 | float64(vectors[i*3+1]), 186 | float64(vectors[i*3+2]), 187 | }, 188 | } 189 | } 190 | return 191 | } 192 | 193 | // TODO(jbd): Remove close? 194 | func (m *manager) close() error { 195 | done := make(chan struct{}) 196 | m.inout <- inOut{ 197 | in: closeSignal{}, 198 | out: done, 199 | } 200 | <-done 201 | return nil 202 | } 203 | 204 | var intToType = map[int]Type{ 205 | C.ASENSOR_TYPE_ACCELEROMETER: Accelerometer, 206 | C.ASENSOR_TYPE_GYROSCOPE: Gyroscope, 207 | C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer, 208 | } 209 | 210 | func typeToInt(t Type) C.int { 211 | for k, v := range intToType { 212 | if v == t { 213 | return C.int(k) 214 | } 215 | } 216 | return C.int(-1) 217 | } 218 | -------------------------------------------------------------------------------- /android.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build android 6 | 7 | #ifndef GO_SENSORS_ANDROID_H 8 | #define GO_SENSORS_ANDROID_H 9 | 10 | typedef struct GoAndroid_SensorManager { 11 | ASensorEventQueue* queue; 12 | ALooper* looper; 13 | int looperId; 14 | } GoAndroid_SensorManager; 15 | 16 | void GoAndroid_createManager(int looperId, GoAndroid_SensorManager* dst); 17 | void GoAndroid_destroyManager(GoAndroid_SensorManager* m); 18 | int GoAndroid_enableSensor(ASensorEventQueue*, int, int32_t); 19 | void GoAndroid_disableSensor(ASensorEventQueue*, int); 20 | int GoAndroid_readQueue(int looperId, ASensorEventQueue* q, int n, int32_t* types, int64_t* timestamps, float* vectors); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /darwin_armx.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin 6 | // +build arm arm64 7 | 8 | package sensor 9 | 10 | /* 11 | #cgo CFLAGS: -x objective-c 12 | #cgo LDFLAGS: -framework CoreMotion 13 | #import "darwin_armx.h" 14 | */ 15 | import "C" 16 | import ( 17 | "fmt" 18 | "sync" 19 | "time" 20 | "unsafe" 21 | ) 22 | 23 | var ( 24 | mu sync.Mutex 25 | doneA chan struct{} 26 | ) 27 | 28 | type manager struct { 29 | m unsafe.Pointer 30 | } 31 | 32 | func (m *manager) initialize() { 33 | m.m = unsafe.Pointer(C.GoIOS_createManager()) 34 | } 35 | 36 | func (m *manager) enable(s sender, t Type, delay time.Duration) error { 37 | // TODO(jbd): If delay is smaller than 10 milliseconds, set it to 38 | // 10 milliseconds. It is highest frequency iOS SDK suppports and 39 | // we don't want to have time.Tick durations smaller than this value. 40 | mu.Lock() 41 | mu.Unlock() 42 | 43 | switch t { 44 | case Accelerometer: 45 | if doneA != nil { 46 | return fmt.Errorf("sensor: cannot enable; %v sensor is already enabled", t) 47 | } 48 | // TODO(jbd): Check if acceloremeter is available. 49 | C.GoIOS_startAccelerometer(m.m) 50 | m.startAccelometer(s, delay) 51 | doneA = make(chan struct{}) 52 | case Gyroscope: 53 | case Magnetometer: 54 | default: 55 | return fmt.Errorf("sensor: unknown sensor type: %v", t) 56 | } 57 | return nil 58 | } 59 | 60 | func (m *manager) disable(t Type) error { 61 | mu.Lock() 62 | mu.Unlock() 63 | 64 | switch t { 65 | case Accelerometer: 66 | if doneA == nil { 67 | return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t) 68 | } 69 | doneA <- struct{}{} 70 | C.GoIOS_stopAccelerometer(m.m) 71 | doneA = nil 72 | case Gyroscope: 73 | case Magnetometer: 74 | default: 75 | return fmt.Errorf("sensor: unknown sensor type: %v", t) 76 | } 77 | return nil 78 | } 79 | 80 | func (m *manager) startAccelometer(app sender, d time.Duration) { 81 | go func() { 82 | ev := make([]C.float, 4) 83 | var lastTimestamp int64 84 | for { 85 | select { 86 | case <-doneA: 87 | return 88 | default: 89 | C.GoIOS_readAccelerometer(m.m, (*C.float)(unsafe.Pointer(&ev[0]))) 90 | t := int64(ev[0] * 1000 * 1000) 91 | if t > lastTimestamp { 92 | // TODO(jbd): Do we need to convert the values to another unit? 93 | // How does iOS units compate to the Android units. 94 | app.Send(Event{ 95 | Sensor: Accelerometer, 96 | Timestamp: t, 97 | Data: []float64{float64(ev[1]), float64(ev[2]), float64(ev[3])}, 98 | }) 99 | lastTimestamp = t 100 | <-time.Tick(d) 101 | } else { 102 | <-time.Tick(d / 2) 103 | } 104 | } 105 | } 106 | }() 107 | } 108 | 109 | // TODO(jbd): Remove close? 110 | func (m *manager) close() error { 111 | C.GoIOS_destroyManager(m.m) 112 | return nil 113 | } 114 | -------------------------------------------------------------------------------- /darwin_armx.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin 6 | // +build arm arm64 7 | 8 | #ifndef GO_SENSORS_IOS_H 9 | #define GO_SENSORS_IOS_H 10 | 11 | #import 12 | 13 | void* GoIOS_createManager(); 14 | 15 | int GoIOS_startAccelerometer(void* m); 16 | int GoIOS_stopAccelerometer(void* m); 17 | void GoIOS_readAccelerometer(void* m, float* vectors); 18 | 19 | void GoIOS_destroyManager(void* m); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /darwin_armx.m: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin 6 | // +build arm arm64 7 | 8 | #import 9 | 10 | void* GoIOS_createManager() { 11 | return [[CMMotionManager alloc] init]; 12 | } 13 | 14 | int GoIOS_startAccelerometer(void* m) { 15 | [((CMMotionManager*)m) startAccelerometerUpdates]; 16 | return 0; 17 | } 18 | 19 | int GoIOS_stopAccelerometer(void* m) { 20 | [((CMMotionManager*)m) stopAccelerometerUpdates]; 21 | return 0; 22 | } 23 | 24 | void GoIOS_readAccelerometer(void* m, float* v) { 25 | CMAccelerometerData* data = ((CMMotionManager*)m).accelerometerData; 26 | v[0] = (float)data.timestamp; 27 | v[1] = data.acceleration.x; 28 | v[2] = data.acceleration.y; 29 | v[3] = data.acceleration.z; 30 | } 31 | 32 | void GoIOS_destroyManager(void* m) { 33 | [((CMMotionManager*)m) release]; 34 | } 35 | -------------------------------------------------------------------------------- /example/example.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin linux 6 | 7 | // An app that draws a green triangle on a red background. 8 | // 9 | // Note: This demo is an early preview of Go 1.5. In order to build this 10 | // program as an Android APK using the gomobile tool. 11 | // 12 | // See http://godoc.org/golang.org/x/mobile/cmd/gomobile to install gomobile. 13 | // 14 | // Get the basic example and use gomobile to build or install it on your device. 15 | // 16 | // $ go get -d golang.org/x/mobile/example/basic 17 | // $ gomobile build golang.org/x/mobile/example/basic # will build an APK 18 | // 19 | // # plug your Android device to your computer or start an Android emulator. 20 | // # if you have adb installed on your machine, use gomobile install to 21 | // # build and deploy the APK to an Android target. 22 | // $ gomobile install golang.org/x/mobile/example/basic 23 | // 24 | // Switch to your device or emulator to start the Basic application from 25 | // the launcher. 26 | // You can also run the application on your desktop by running the command 27 | // below. (Note: It currently doesn't work on Windows.) 28 | // $ go install golang.org/x/mobile/example/basic && basic 29 | package main 30 | 31 | import ( 32 | "encoding/binary" 33 | "log" 34 | "time" 35 | 36 | "github.com/rakyll/sensors" 37 | "golang.org/x/mobile/app" 38 | "golang.org/x/mobile/event/lifecycle" 39 | "golang.org/x/mobile/event/paint" 40 | "golang.org/x/mobile/event/size" 41 | "golang.org/x/mobile/event/touch" 42 | "golang.org/x/mobile/exp/app/debug" 43 | "golang.org/x/mobile/exp/f32" 44 | "golang.org/x/mobile/exp/gl/glutil" 45 | "golang.org/x/mobile/gl" 46 | ) 47 | 48 | var ( 49 | program gl.Program 50 | position gl.Attrib 51 | offset gl.Uniform 52 | color gl.Uniform 53 | buf gl.Buffer 54 | 55 | green float32 56 | touchX float32 57 | touchY float32 58 | ) 59 | 60 | func main() { 61 | app.Main(func(a app.App) { 62 | sensor.Enable(a, sensor.Accelerometer, 100*time.Millisecond) 63 | 64 | var sz size.Event 65 | for e := range a.Events() { 66 | switch e := app.Filter(e).(type) { 67 | case lifecycle.Event: 68 | switch e.Crosses(lifecycle.StageVisible) { 69 | case lifecycle.CrossOn: 70 | onStart() 71 | case lifecycle.CrossOff: 72 | onStop() 73 | } 74 | case size.Event: 75 | sz = e 76 | touchX = float32(sz.WidthPx / 2) 77 | touchY = float32(sz.HeightPx / 2) 78 | case paint.Event: 79 | onPaint(sz) 80 | a.EndPaint(e) 81 | case touch.Event: 82 | touchX = e.X 83 | touchY = e.Y 84 | case sensor.Event: 85 | // do nothing 86 | } 87 | } 88 | }) 89 | } 90 | 91 | func onStart() { 92 | var err error 93 | program, err = glutil.CreateProgram(vertexShader, fragmentShader) 94 | if err != nil { 95 | log.Printf("error creating GL program: %v", err) 96 | return 97 | } 98 | 99 | buf = gl.CreateBuffer() 100 | gl.BindBuffer(gl.ARRAY_BUFFER, buf) 101 | gl.BufferData(gl.ARRAY_BUFFER, triangleData, gl.STATIC_DRAW) 102 | 103 | position = gl.GetAttribLocation(program, "position") 104 | color = gl.GetUniformLocation(program, "color") 105 | offset = gl.GetUniformLocation(program, "offset") 106 | 107 | // TODO(crawshaw): the debug package needs to put GL state init here 108 | // Can this be an app.RegisterFilter call now?? 109 | } 110 | 111 | func onStop() { 112 | gl.DeleteProgram(program) 113 | gl.DeleteBuffer(buf) 114 | } 115 | 116 | func onPaint(sz size.Event) { 117 | gl.ClearColor(1, 0, 0, 1) 118 | gl.Clear(gl.COLOR_BUFFER_BIT) 119 | 120 | gl.UseProgram(program) 121 | 122 | green += 0.01 123 | if green > 1 { 124 | green = 0 125 | } 126 | gl.Uniform4f(color, 0, green, 0, 1) 127 | 128 | gl.Uniform2f(offset, touchX/float32(sz.WidthPx), touchY/float32(sz.HeightPx)) 129 | 130 | gl.BindBuffer(gl.ARRAY_BUFFER, buf) 131 | gl.EnableVertexAttribArray(position) 132 | gl.VertexAttribPointer(position, coordsPerVertex, gl.FLOAT, false, 0, 0) 133 | gl.DrawArrays(gl.TRIANGLES, 0, vertexCount) 134 | gl.DisableVertexAttribArray(position) 135 | 136 | debug.DrawFPS(sz) 137 | } 138 | 139 | var triangleData = f32.Bytes(binary.LittleEndian, 140 | 0.0, 0.4, 0.0, // top left 141 | 0.0, 0.0, 0.0, // bottom left 142 | 0.4, 0.0, 0.0, // bottom right 143 | ) 144 | 145 | const ( 146 | coordsPerVertex = 3 147 | vertexCount = 3 148 | ) 149 | 150 | const vertexShader = `#version 100 151 | uniform vec2 offset; 152 | 153 | attribute vec4 position; 154 | void main() { 155 | // offset comes in with x/y values between 0 and 1. 156 | // position bounds are -1 to 1. 157 | vec4 offset4 = vec4(2.0*offset.x-1.0, 1.0-2.0*offset.y, 0, 0); 158 | gl_Position = position + offset4; 159 | }` 160 | 161 | const fragmentShader = `#version 100 162 | precision mediump float; 163 | uniform vec4 color; 164 | void main() { 165 | gl_FragColor = color; 166 | }` 167 | -------------------------------------------------------------------------------- /notmobile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build linux,!android darwin,!arm,!arm64 6 | 7 | package sensor 8 | 9 | import ( 10 | "errors" 11 | "time" 12 | ) 13 | 14 | type manager struct{} 15 | 16 | func (m *manager) initialize() {} 17 | 18 | func (m *manager) enable(s sender, t Type, delay time.Duration) error { 19 | return errors.New("sensor: no sensors available") 20 | } 21 | 22 | func (m *manager) disable(t Type) error { 23 | return errors.New("sensor: no sensors available") 24 | } 25 | 26 | func (m *manager) close() error { 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /sensor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package sensor provides sensor events from various movement sensors. 6 | package sensor 7 | 8 | import ( 9 | "errors" 10 | "time" 11 | ) 12 | 13 | // Type represents a sensor type. 14 | type Type int 15 | 16 | var sensorNames = map[Type]string{ 17 | Accelerometer: "Accelerometer", 18 | Gyroscope: "Gyrsocope", 19 | Magnetometer: "Magnetometer", 20 | } 21 | 22 | // String returns the string representation of the sensor type. 23 | func (t Type) String() string { 24 | if n, ok := sensorNames[t]; ok { 25 | return n 26 | } 27 | return "Unknown sensor" 28 | } 29 | 30 | const ( 31 | Accelerometer = Type(0) 32 | Gyroscope = Type(1) 33 | Magnetometer = Type(2) 34 | ) 35 | 36 | // Event represents a sensor event. 37 | type Event struct { 38 | // Sensor is the type of the sensor the event is coming from. 39 | Sensor Type 40 | 41 | // Timestamp is a device specific event time in nanoseconds. 42 | // Timestamps are not Unix times, they represent a time that is 43 | // only valid for the device's default sensor. 44 | Timestamp int64 45 | 46 | // Data is the event data. 47 | // 48 | // If the event source is Accelerometer, 49 | // - Data[0]: acceleration force in x axis in m/s^2 50 | // - Data[1]: acceleration force in y axis in m/s^2 51 | // - Data[2]: acceleration force in z axis in m/s^2 52 | // 53 | // If the event source is Gyroscope, 54 | // - Data[0]: rate of rotation around the x axis in rad/s 55 | // - Data[1]: rate of rotation around the y axis in rad/s 56 | // - Data[2]: rate of rotation around the z axis in rad/s 57 | // 58 | // If the event source is Magnetometer, 59 | // - Data[0]: force of gravity along the x axis in m/s^2 60 | // - Data[1]: force of gravity along the y axis in m/s^2 61 | // - Data[2]: force of gravity along the z axis in m/s^2 62 | // 63 | Data []float64 64 | } 65 | 66 | // TODO(jbd): Remove sender and couple the package with x/mobile/app? 67 | type sender interface { 68 | Send(event interface{}) 69 | } 70 | 71 | // m is the underlying platform-specific sensor manager. 72 | var m *manager 73 | 74 | // Enable enables the specified sensor type with the given delay rate. 75 | // Sensor events will be sent to the s that implements Send(event interface{}). 76 | func Enable(s sender, t Type, delay time.Duration) error { 77 | if t < 0 || int(t) >= len(sensorNames) { 78 | return errors.New("sensor: unknown sensor type") 79 | } 80 | return m.enable(s, t, delay) 81 | } 82 | 83 | // Disable disables to feed the manager with the specified sensor. 84 | func Disable(t Type) error { 85 | if t < 0 || int(t) >= len(sensorNames) { 86 | return errors.New("sensor: unknown sensor type") 87 | } 88 | return m.disable(t) 89 | } 90 | 91 | func init() { 92 | m = new(manager) 93 | m.initialize() 94 | } 95 | --------------------------------------------------------------------------------