-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathRemotePane.go
157 lines (125 loc) · 2.85 KB
/
RemotePane.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package remote
import (
"encoding/gob"
"fmt"
"image"
"net"
"time"
"github.com/ninjasphere/gestic-tools/go-gestic-sdk"
"github.com/ninjasphere/go-ninja/config"
"github.com/ninjasphere/go-ninja/logger"
)
// This is the maximum time we will wait for a frame before disconnecting the remote pane
var remotePaneTimeout = config.Duration(time.Second, "led.remote.paneTimeout")
type Pane struct {
Disconnected chan bool
log *logger.Logger
conn net.Conn
incoming *gob.Decoder
outgoing *gob.Encoder
enabled bool
incomingFrames chan *Incoming
keepAwake bool
locked bool
}
type Outgoing struct {
FrameRequested bool
Gesture *gestic.GestureMessage
}
type Incoming struct {
Image *image.RGBA
Err error
KeepAwake bool
Locked bool
}
func NewPane(conn net.Conn) *Pane {
pane := &Pane{
conn: conn,
log: logger.GetLogger("Pane"),
Disconnected: make(chan bool, 1),
incoming: gob.NewDecoder(conn),
outgoing: gob.NewEncoder(conn),
enabled: true,
incomingFrames: make(chan *Incoming, 1),
}
// Ping the remote pane continuously so we can see if it's disappeared.
// This is kinda dumb.
go func() {
for {
if !pane.enabled {
break
}
pane.out(Outgoing{})
time.Sleep(time.Second)
}
}()
go pane.listen()
return pane
}
func (p *Pane) IsEnabled() bool {
return p.enabled
}
func (p *Pane) KeepAwake() bool {
return p.keepAwake
}
func (p *Pane) Locked() bool {
return p.locked
}
func (p *Pane) Gesture(gesture *gestic.GestureMessage) {
if !p.enabled {
return
}
if gesture.Gesture.Gesture != gestic.GestureNone || gesture.Touch.Active() || gesture.Tap.Active() || gesture.DoubleTap.Active() || gesture.AirWheel.Active {
p.out(Outgoing{false, gesture})
}
}
func (p *Pane) out(msg Outgoing) error {
err := p.outgoing.Encode(msg)
if err != nil {
p.log.Errorf("Failed to gob encode outgoing remote message: %s", err)
p.Close()
}
return err
}
func (p *Pane) listen() {
for {
var msg Incoming
err := p.incoming.Decode(&msg)
//p.log.Debugf("Got an incoming message")
if err != nil {
p.Close()
break
}
p.keepAwake = msg.KeepAwake
p.locked = msg.Locked
p.incomingFrames <- &msg
}
}
func (p *Pane) Render() (*image.RGBA, error) {
if !p.enabled {
return nil, fmt.Errorf("This remote pane has disconnected.")
}
err := p.out(Outgoing{true, nil})
if err != nil {
return nil, err
}
select {
case msg := <-p.incomingFrames:
//p.log.Debugf("Got incoming remote message")
return msg.Image, msg.Err
case <-time.After(remotePaneTimeout):
p.log.Errorf("Remote pane timed out")
p.Close()
return nil, fmt.Errorf("Remote pane timed out")
}
}
func (p *Pane) Close() {
if p.enabled {
p.enabled = false
p.conn.Close()
p.Disconnected <- true
}
}
func (p *Pane) IsDirty() bool {
return true
}