-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvrpn_Dial.C
216 lines (181 loc) · 6.23 KB
/
vrpn_Dial.C
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
209
210
211
212
213
214
215
216
#include <stdio.h> // for fprintf, stderr, NULL
#include "vrpn_Connection.h" // for vrpn_Connection, etc
#include "vrpn_Dial.h"
//#define VERBOSE
vrpn_Dial::vrpn_Dial (const char * name, vrpn_Connection * c) :
vrpn_BaseClass(name, c)
{
vrpn_BaseClass::init();
num_dials = 0;
// Set the time to 0 just to have something there.
timestamp.tv_usec = timestamp.tv_sec = 0;
}
int vrpn_Dial::register_types(void)
{
if (d_connection == NULL) {
return 0;
}
change_m_id = d_connection->register_message_type("vrpn_Dial update");
if (change_m_id == -1) {
fprintf(stderr,"vrpn_Dial: Can't register type IDs\n");
d_connection = NULL;
}
return 0;
}
vrpn_int32 vrpn_Dial::encode_to(char *buf, vrpn_int32 buflen, vrpn_int32 dial, vrpn_float64 delta)
{
vrpn_int32 buflensofar = buflen;
// Message includes: vrpn_int32 dialNum, vrpn_float64 delta
// We pack them with the delta first, so that everything is aligned
// on the proper boundary.
if (vrpn_buffer( &buf, &buflensofar, delta)) {
fprintf(stderr,"vrpn_Dial::encode_to: Can't buffer delta\n");
return -1;
}
if (vrpn_buffer( &buf, &buflensofar, dial)) {
fprintf(stderr,"vrpn_Dial::encode_to: Can't buffer dial\n");
return -1;
}
return sizeof(vrpn_float64) + sizeof(vrpn_int32);
}
// This will report any changes that have appeared in the dial values,
// and then clear the dials back to 0. It only sends dials that have
// changed (nonzero values)
void vrpn_Dial::report_changes (void) {
char msgbuf[1000];
vrpn_int32 i;
vrpn_int32 len;
if (d_connection) {
for (i = 0; i < num_dials; i++) {
if (dials[i] != 0) {
len = encode_to(msgbuf, sizeof(msgbuf), i, dials[i]);
if (d_connection->pack_message(len, timestamp,
change_m_id, d_sender_id, msgbuf, vrpn_CONNECTION_RELIABLE)) {
fprintf(stderr,"vrpn_Dial: can't write message: tossing\n");
}
dials[i] = 0; // We've reported it the change.
}
}
}
}
// This will report the dials whether they have changed or not; this
// will result in some 0 dial values being sent. Normally, code will
// use the report_changes method to avoid flooding the system with
// un-needed messages.
// It then clears the dials back to 0.
void vrpn_Dial::report (void) {
char msgbuf[1000];
vrpn_int32 i;
vrpn_int32 len;
if (d_connection) {
for (i = 0; i < num_dials; i++) {
len = encode_to(msgbuf, sizeof(msgbuf), i, dials[i]);
if (d_connection->pack_message(len, timestamp,
change_m_id, d_sender_id, msgbuf, vrpn_CONNECTION_RELIABLE)) {
fprintf(stderr,"vrpn_Dial: can't write message: tossing\n");
}
dials[i] = 0; // We've reported it the change.
}
}
}
// ************* EXAMPLE SERVER ROUTINES ****************************
static unsigned long duration(struct timeval t1, struct timeval t2)
{
return (t1.tv_usec - t2.tv_usec) +
1000000L * (t1.tv_sec - t2.tv_sec);
}
vrpn_Dial_Example_Server::vrpn_Dial_Example_Server(const char * name, vrpn_Connection * c,
vrpn_int32 numdials, vrpn_float64 spin_rate, vrpn_float64 update_rate) :
vrpn_Dial(name, c), // Construct the base class, which registers message/sender
_spin_rate(spin_rate), // Set the rate at which the dials will spin
_update_rate(update_rate) // Set the rate at which to generate reports
{
// Make sure we asked for a legal number of dials
if (num_dials > vrpn_DIAL_MAX) {
fprintf(stderr,"vrpn_Dial_Example_Server: Only using %d dials\n",
vrpn_DIAL_MAX);
num_dials = vrpn_DIAL_MAX;
} else {
num_dials = numdials;
}
// IN A REAL SERVER, open the device that will service the dials here
}
void vrpn_Dial_Example_Server::mainloop()
{
struct timeval current_time;
int i;
// Call the generic server mainloop, since we are a server
server_mainloop();
// See if its time to generate a new report
// IN A REAL SERVER, this check would not be done; although the
// time of the report would be updated to the current time so
// that the correct timestamp would be issued on the report.
vrpn_gettimeofday(¤t_time, NULL);
if ( duration(current_time,timestamp) >= 1000000.0/_update_rate) {
// Update the time
timestamp.tv_sec = current_time.tv_sec;
timestamp.tv_usec = current_time.tv_usec;
// Update the values for the dials, to say that each one has
// moved the appropriate rotation (spin rate is revolutions per
// second, update rate is report/second, the quotient is the number
// of revolutions since the last report). When the changes are
// reported, these values are set back to zero.
// THIS CODE WILL BE REPLACED by the user code that tells how
// many revolutions each dial has changed since the last report.
for (i = 0; i < num_dials; i++) {
dials[i] = _spin_rate / _update_rate;
}
// Send reports. Stays the same in a real server.
report_changes();
}
}
// ************* CLIENT ROUTINES ****************************
vrpn_Dial_Remote::vrpn_Dial_Remote (const char * name,
vrpn_Connection * c) :
vrpn_Dial (name, c)
{
vrpn_int32 i;
// Register a handler for the change callback from this device,
// if we got a connection.
if (d_connection) {
if (register_autodeleted_handler(change_m_id, handle_change_message,
this, d_sender_id)) {
fprintf(stderr,"vrpn_Dial_Remote: can't register handler\n");
d_connection = NULL;
}
} else {
fprintf(stderr,"vrpn_Dial_Remote: Can't get connection!\n");
}
// At the start, as far as the client knows, the device could have
// max channels -- the number of channels is specified in each
// message.
num_dials=vrpn_DIAL_MAX;
for (i = 0; i < vrpn_DIAL_MAX; i++) {
dials[i] = 0.0;
}
vrpn_gettimeofday(×tamp, NULL);
}
vrpn_Dial_Remote::~vrpn_Dial_Remote()
{
}
void vrpn_Dial_Remote::mainloop()
{
client_mainloop();
if (d_connection) {
d_connection->mainloop();
}
}
int vrpn_Dial_Remote::handle_change_message(void *userdata,
vrpn_HANDLERPARAM p)
{
vrpn_Dial_Remote *me = (vrpn_Dial_Remote *)userdata;
vrpn_DIALCB cp;
const char *bufptr = p.buffer;
cp.msg_time = p.msg_time;
vrpn_unbuffer(&bufptr, &cp.change);
vrpn_unbuffer(&bufptr, &cp.dial);
// Go down the list of callbacks that have been registered.
// Fill in the parameter and call each.
me->d_callback_list.call_handlers(cp);
return 0;
}