1
/******************************************/
4
by Gary P. Scavone, 2000
6
This object will accept control messages
7
from a variety of sources, such as a MIDI
8
port, scorefile, socket connection, or
9
pipe. MIDI messages are retrieved with
10
the RtMidi class. All other input sources
11
(scorefile, socket, or pipe) are assumed
12
to provide SKINI formatted messages.
14
For each call of getNextMessage(), the
15
active input devices are queried to see
16
if a new control message is available.
17
Only one message per call is returned, so
18
a subsequent call begins querying the
19
next available device "after" the previously
22
This class is primarily for use in STK
25
One of my original goals in creating this class
26
was to simplify the message acquisition process
27
by removing all threads. If the windoze
28
select() function behaved just like the unix one,
29
that would have been possible. Since it does not
30
(it can't be used to poll STDIN), I am using a
31
thread to acquire messages from STDIN, which are
32
then sent via a socket connection to the message
33
socket server. Perhaps in the future, I will be
34
able to simplify things.
36
/******************************************/
38
#include "Controller.h"
40
Controller :: Controller(int inputMask)
43
default_ticks = RT_BUFFER_SIZE;
46
score = new SKINI11();
48
#if defined(__STK_REALTIME_)
52
struct sockaddr_in mysocket;
56
The fd array is used to hold the file descriptors for
57
all connected sockets. This saves some time incrementing
58
through file descriptors when using select().
60
for (int i=0; i<16; i++)
63
if ( source & STK_MIDI )
64
midi_input = new RtMidi();
67
If no input source is specified, we assume the input is coming
68
from a SKINI scorefile. If any input source is specified, we
69
will always check STDIN, even in STK_PIPE is not specified.
70
This provides a means to exit cleanly when reading MIDI or
71
in case a socket connection cannot be made after STK_SOCKET has
72
been specified. The current means of polling STDIN is via a
76
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
77
if (pthread_create(&stdin_thread, NULL, stdinHandler, NULL)) {
78
#elif defined(__OS_Win_)
79
stdin_thread = _beginthread(stdinHandler, 0, NULL);
80
if (stdin_thread == 0) {
82
sprintf(msg, "Controller: unable to create stdin socket thread!\n");
83
throw StkError(msg, StkError::PROCESS_THREAD);
88
/* Let the user know that they can exit the program via the console
91
if ( !(source & STK_PIPE) && inputMask )
92
printf("\nType `Exit<cr>' to quit.\n\n");
94
if ( source & STK_SOCKET ) {
95
// Set up the socket server to accept remote connections
96
#if defined(__OS_Win_) // Windoze-only stuff
98
WORD wVersionRequested = MAKEWORD(1,1);
100
WSAStartup(wVersionRequested, &wsaData);
101
if (wsaData.wVersion != wVersionRequested) {
102
sprintf(msg, "Controller: Wrong Windoze socket library version!\n");
103
throw StkError(msg, StkError::PROCESS_SOCKET);
107
// Create the server-side socket
108
local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
109
if (local_socket < 0) {
110
sprintf(msg, "Controller: Couldn't create socket!\n");
111
throw StkError(msg, StkError::PROCESS_SOCKET);
114
mysocket.sin_family=AF_INET;
115
mysocket.sin_addr.s_addr=INADDR_ANY;
116
mysocket.sin_port=htons(STK_SOCKET_PORT);
118
// Bind socket to the appropriate port and interface (INADDR_ANY)
119
if (bind(local_socket, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0) {
120
sprintf(msg, "Controller: Couldn't bind socket!\n");
121
throw StkError(msg, StkError::PROCESS_SOCKET);
124
// Listen for one incoming connection
125
if (listen(local_socket, 1) < 0) {
126
sprintf(msg, "Controller: Couldn't set up listen on socket!\n");
127
throw StkError(msg, StkError::PROCESS_SOCKET);
129
if (inputMask & STK_SOCKET)
130
// Only print the message if STK_SOCKET was initially specified
131
printf("Listening for a connection on port %d\n\n", STK_SOCKET_PORT);
133
FD_SET(local_socket, &mask);
134
if (local_socket > maxfd) maxfd = local_socket;
136
#endif // __STK_REALTIME
139
Controller :: ~Controller()
143
#if defined(__STK_REALTIME_)
145
if ( source & STK_MIDI )
148
if ( source & STK_SOCKET ) {
149
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
150
shutdown(local_socket,0);
151
pthread_cancel(stdin_thread);
152
pthread_join(stdin_thread, NULL);
153
#elif defined(__OS_Win_)
154
TerminateThread((HANDLE)stdin_thread,0);
155
closesocket(local_socket);
159
#endif // __STK_REALTIME
162
int Controller :: getType()
167
MY_FLOAT Controller :: getByte2()
172
MY_FLOAT Controller :: getByte3()
177
MY_FLOAT Controller :: getChannel()
182
void Controller :: setDefaultTicks(long nSamples)
184
default_ticks = nSamples;
187
int Controller :: getNextMessage()
189
#if defined(__STK_REALTIME_)
191
static struct timeval timeout = {0, 0};
192
static int device = 0;
193
static int nSockets = 0;
194
static int fd_thread = 0;
199
// reset message type
203
// no realtime flags ... assuming scorefile input
204
memset(message[msg_index], 0, MESSAGE_LENGTH);
205
if ( fgets(message[msg_index], MESSAGE_LENGTH, stdin) == 0 )
210
#if defined(__STK_REALTIME_)
212
if (num_messages > 0)
215
while (checked < nSockets+1) {
217
if ( source & STK_SOCKET ) {
220
if (select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout)) {
221
// there is a file descriptor set
223
// check whether there's a new socket connection available
224
if ( FD_ISSET(local_socket, &rmask) ) {
225
// accept and service new connection
226
int remote_socket=accept(local_socket, NULL, NULL);
227
if (remote_socket < 0) {
228
sprintf(msg, "Controller: Couldn't accept connection request!\n");
229
throw StkError(msg, StkError::PROCESS_SOCKET);
232
// print message for connections subsequent to "piping" socket
233
printf("New socket connection made.\n\n");
235
// set the socket non-blocking
236
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
237
fcntl(remote_socket, F_SETFL, O_NONBLOCK);
238
#elif defined(__OS_Win_)
239
unsigned long non_block = 1;
240
ioctlsocket(remote_socket, FIONBIO, &non_block);
243
fd[nSockets] = remote_socket;
244
if (nSockets == 0) fd_thread = remote_socket;
246
FD_SET(remote_socket, &mask);
247
if ( remote_socket > maxfd) maxfd = remote_socket;
248
FD_CLR(local_socket, &rmask);
253
// check socket connections
254
while (device < nSockets) {
255
if (FD_ISSET(fd[device], &rmask)) {
256
// this socket has data
257
i = parseSocketData(fd[device]);
259
// the socket connection closed
263
if ( nSockets == 1 && FD_ISSET(fd_thread, &mask) ) {
264
// the "piping" socket is still running
265
if (source & STK_MIDI) {
266
printf("MIDI input still running ... type 'Exit<cr>' to quit.\n\n");
269
else if (!(source & STK_PIPE) )
272
if (device < nSockets) {
273
// move descriptors down in the list
274
for (int j=device; j<nSockets; j++)
283
if ( !strncmp(message[msg_index], "Exit", 4) || !strncmp(message[msg_index], "exit", 4) ) {
284
// we have an "Exit" message ... ignore it
288
// not an "Exit" message ... parse it
292
if (++checked >= nSockets+1) break;
295
else { // no file descriptors were set
302
if (device >= nSockets) {
303
//printf("got here, nSockets = %d, checked = %d, device = %d\n", nSockets, checked, device);
305
if (source & STK_MIDI) {
306
if ( midi_input->nextMessage() > 0 ) {
307
// get MIDI message info
308
type = midi_input->getType();
309
channel = midi_input->getChannel();
310
byte2 = midi_input->getByteTwo();
311
byte3 = midi_input->getByteThree();
312
return default_ticks;
315
if (++checked >= nSockets+1) break;
318
// if we get here, we checked all devices but found no messages
319
return default_ticks;
321
#endif // __STK_REALTIME
325
//printf("%s", message[msg_index]);
327
score->parseThis(message[msg_index++]);
329
if (msg_index >= MAX_MESSAGES) msg_index = 0;
330
type = score->getType();
332
MY_FLOAT temp = score->getDelta();
334
ticks = (long) (temp * SRATE);
336
// negative delta times specify realtime messages
337
ticks = default_ticks;
339
channel = score->getChannel();
340
byte2 = score->getByteTwo();
341
byte3 = score->getByteThree();
344
// Don't tick for comments or improperly formatted messages
351
#if defined(__STK_REALTIME_)
353
int Controller :: parseSocketData(int fd)
356
Parsing the socket data buffer is complicated by the fact that
357
multiple and sometimes incomplete socket messages can be returned
358
from a single recv() call, especially during high socket activity.
359
This method will read all data available from a socket connection,
360
filling the message buffer. This is necessary because the select()
361
function triggers on socket activity, not on the presence of
362
(buffered) data. So, whenever activity is indicated, we need to
363
grab all available data.
366
static char socket_buffer[MESSAGE_LENGTH];
367
int index = 0, m = 0, bufsize = 0;
370
fill_msg = (msg_index + num_messages) % MAX_MESSAGES;
371
memset(message[fill_msg], 0, MESSAGE_LENGTH);
373
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
375
while (bufsize != -1 && errno != EAGAIN) {
376
#elif defined(__OS_Win_)
377
while (bufsize != SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
379
while (index < bufsize) {
380
message[fill_msg][m++] = socket_buffer[index];
381
if (socket_buffer[index++] == '\n') {
384
fill_msg = (msg_index + num_messages) % MAX_MESSAGES;
385
memset(message[fill_msg], 0, MESSAGE_LENGTH);
390
// receive a new socket buffer
391
memset(socket_buffer, 0, MESSAGE_LENGTH);
392
bufsize = recv(fd, socket_buffer, MESSAGE_LENGTH, 0);
395
#if defined(__OS_Win_)
407
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
409
void *stdinHandler(void *)
411
#elif defined(__OS_Win_)
413
void stdinHandler(void *)
417
char message[MESSAGE_LENGTH];
420
struct sockaddr_in server_address;
422
#if defined(__OS_Win_) // Windoze-only stuff
424
WORD wVersionRequested = MAKEWORD(1,1);
426
WSAStartup(wVersionRequested, &wsaData);
427
if (wsaData.wVersion != wVersionRequested) {
428
sprintf(msg, "Controller: Wrong Windoze socket library version!\n");
429
throw StkError(msg, StkError::PROCESS_SOCKET);
433
// Create the client-side socket
434
local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
435
if (local_socket < 0) {
436
sprintf(msg, "Controller: Couldn't create socket!\n");
437
throw StkError(msg, StkError::PROCESS_SOCKET);
440
struct hostent *hostp;
441
hostp = gethostbyname("localhost");
443
// Fill in the address structure
444
server_address.sin_family = AF_INET;
445
memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length);
446
server_address.sin_port = htons(STK_SOCKET_PORT);
448
// Connect to the server
449
if (connect(local_socket, (struct sockaddr *)&server_address,
450
sizeof(server_address) ) < 0) {
451
#if defined(__OS_Win_)
452
closesocket(local_socket);
457
sprintf(msg, "Controller: Couldn't connect stdin socket thread to server!\n");
458
throw StkError(msg, StkError::PROCESS_SOCKET);
462
memset(message, 0, MESSAGE_LENGTH);
463
if ( fgets(message, MESSAGE_LENGTH, stdin) == 0 )
465
// check for an "Exit" message
466
if ( !strncmp(message, "Exit", 4) || !strncmp(message, "exit", 4) )
469
if (send(local_socket, (const char *)message, strlen(message), 0) < 0) {
470
#if defined(__OS_Win_)
471
closesocket(local_socket);
476
sprintf(msg, "Controller: connection to socket server failed!\n");
477
throw StkError(msg, StkError::PROCESS_SOCKET);
481
#if defined(__OS_Win_)
482
closesocket(local_socket);
490
#endif // __STK_REALTIME