-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconnect.go
208 lines (194 loc) · 7.46 KB
/
connect.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package main
import (
"fmt"
"github.com/chinenual/synergize/io"
"github.com/chinenual/synergize/logger"
"github.com/chinenual/synergize/osc"
"github.com/chinenual/synergize/synio"
"github.com/chinenual/synergize/zeroconf"
"github.com/pkg/errors"
)
// Synergy and Control Surface connection can be configured from the command line,
// hardcoded in the preferences file, or auto-configured via zeroconf.
// Orchestrate the initializations from here...
//
// Connection/Zeroconf Lifecycle:
// OSC server (re)started when:
// voicing mode starts
// OSC client (re)started when:
// voicing mode starts
//
// VST client started when:
// first time IO requiring synergy connection
// user explictly connects
// load CRT for editing
// load CRT
// load SYN
// save SYN
// disable VRAM
// run COMTest
// toggle voicing mode
//
// zeroconf browses when:
// at program startup
// user explicitly asks for a re-scan
//
// zeroconf publishes OSC server address when:
// at program startup
// whenever server restarted
//
// ----------
// Connections are initiated from Javascript due to inability to do a simple synchronous
// dialog initiated from Go. If Go could call javascript and prompt with "choose one of
// these devcies", all would be much more straightforward. But since Javascript requires
// async callbacks from any sort of modal dialog, we have to structure it thusly:
//
// javascript asks go what devices are available
// if zeroconf is not enabled for the device, go returns "already configured" (in which case javascript stops)
// else go can respond with "device is already configured" if we've already been through a zeroconf selection cycle
// (in which case javascript stops)
// or go returns a list of choices
// javascript modal dialog shows the choices. user can choose "rescan" in which case we do
// another zeroconf browse - javascript starts over and reinitates the cycle
// or, user can cancel - (in which case javascript stops)
// or user can choose one of the choices. It then passes that back to go to "connect"
// to the chosen device
var firmwareVersion string
func DisconnectSynergy() (err error) {
firmwareVersion = ""
if err = synio.Close(); err != nil {
return
}
return
}
func DisconnectControlSurface() (err error) {
if err = osc.Quit(); err != nil {
return
}
return
}
func GetSynergyConfig() (hasDevice bool, alreadyConfigured bool, name string, choices *[]zeroconf.Service, err error) {
if !io.SynergyConfigured() {
firmwareVersion = ""
if *mockSynio || *serial {
// Serial port command line option
logger.Infof("ZEROCONF: using -port and -baud commnd line config %s at %d\n", prefsUserPreferences.SerialPort, prefsUserPreferences.SerialBaud)
if err = synio.SetSynergySerialPort(prefsUserPreferences.SerialPort, prefsUserPreferences.SerialBaud,
prefsUserPreferences.SerialFlowControl, true, *serialVerboseFlag, *mockSynio); err != nil {
return
}
} else if *vst != 0 {
// VST command line option
logger.Infof("ZEROCONF: using -VST command line config %d\n", *vst)
if err = synio.SetSynergyVst(fmt.Sprintf("VST localhost:%d", *vst), "localhost", *vst,
true, *serialVerboseFlag, *mockSynio); err != nil {
return
}
} else {
// VST via Zeroconf and possibly a serial port if configured
vstServices := zeroconf.GetVstServices()
logger.Infof("ZEROCONF: zero or more than one VST: %#v\n", vstServices)
if prefsUserPreferences.UseSerial {
var pseudoEntry zeroconf.Service
pseudoEntry.InstanceName = "serial-port"
list := append([]zeroconf.Service{pseudoEntry}, vstServices...)
choices = &list
} else {
choices = &vstServices
}
}
}
hasDevice = true // we assume user has a Synergy or VST
name = io.SynergyName()
alreadyConfigured = io.SynergyConfigured()
return
}
func GetControlSurfaceConfig() (hasDevice bool, alreadyConfigured bool, name string, choices *[]zeroconf.Service, err error) {
if !osc.ControlSurfaceConfigured() && prefsUserPreferences.UseOsc {
if prefsUserPreferences.OscAutoConfig {
oscServices := zeroconf.GetOscServices()
if false && len(oscServices) == 1 {
logger.Infof("ZEROCONF: auto config Control Surface: %#v\n", oscServices[0])
if err = osc.SetControlSurface(oscServices[0].InstanceName, oscServices[0].HostName, oscServices[0].Port); err != nil {
return
}
} else {
logger.Infof("ZEROCONF: zero or more than one Control Surface: %#v\n", oscServices)
choices = &oscServices
}
} else {
logger.Infof("ZEROCONF: Control Surface zeroconf disabled - using preferences config %s:%d\n", prefsUserPreferences.OscCSurfaceAddress, prefsUserPreferences.OscCSurfacePort)
if err = osc.SetControlSurface("", prefsUserPreferences.OscCSurfaceAddress, prefsUserPreferences.OscCSurfacePort); err != nil {
return
}
}
}
hasDevice = prefsUserPreferences.UseOsc
alreadyConfigured = osc.ControlSurfaceConfigured()
name = osc.ControlSurfaceName()
return
}
func GetFirmwareVersion() (id string, err error) {
if firmwareVersion == "" {
if !io.SynergyConfigured() {
err = errors.New("Not connected to a Synergy; can't check firmware version")
return
} else {
var bytes [2]byte
bytes, err = synio.GetID()
if err != nil {
err = errors.Wrap(err, "Cannot get firmware version")
logger.Errorf(err.Error())
return
}
firmwareVersion = fmt.Sprintf("%d.%d", bytes[0], bytes[1])
logger.Infof("Connected to Synergy, firmware version: %s\n", firmwareVersion)
}
}
return
}
func ConnectSynergy(zeroconfConfig zeroconf.Service) (err error) {
// FIXME:ConnectSynergy and ConnectToSynergy are more or less identical except for the "if already connected" check. Consolidate them.
if zeroconfConfig.InstanceName == "serial-port" {
logger.Infof("ZEROCONF: using Synergy preferences config %s at %d\n", prefsUserPreferences.SerialPort, prefsUserPreferences.SerialBaud)
if err = synio.SetSynergySerialPort(prefsUserPreferences.SerialPort, prefsUserPreferences.SerialBaud,
prefsUserPreferences.SerialFlowControl, true, *serialVerboseFlag, *mockSynio); err != nil {
return
}
} else {
logger.Infof("ZEROCONF: using Synergy zeroconf config %s (%s:%d)\n", zeroconfConfig.InstanceName, zeroconfConfig.HostName, zeroconfConfig.Port)
if err = synio.SetSynergyVst(zeroconfConfig.InstanceName, zeroconfConfig.HostName, zeroconfConfig.Port,
true, *serialVerboseFlag, *mockSynio); err != nil {
return
}
}
return
}
func ConnectToSynergy(choice *zeroconf.Service) (err error) {
if !io.SynergyConfigured() {
firmwareVersion = ""
if choice == nil || choice.InstanceName == "serial-port" {
if err = synio.SetSynergySerialPort(prefsUserPreferences.SerialPort,
prefsUserPreferences.SerialBaud, prefsUserPreferences.SerialFlowControl,
true, *serialVerboseFlag, *mockSynio); err != nil {
err = errors.Wrapf(err, "Cannot connect to synergy on port %s at %d baud\n",
prefsUserPreferences.SerialPort,
prefsUserPreferences.SerialBaud)
logger.Errorf(err.Error())
return
}
} else {
// VST
if err = synio.SetSynergyVst(choice.InstanceName, choice.HostName,
choice.Port, true, *serialVerboseFlag, *mockSynio); err != nil {
err = errors.Wrapf(err, "Cannot connect to synergy VST %s at %s:%d\n",
choice.InstanceName, choice.HostName,
choice.Port)
logger.Errorf(err.Error())
return
}
}
logger.Infof("Connected to Synergy %s\n", io.SynergyName())
}
return
}