~ubuntu-branches/ubuntu/breezy/muse/breezy

« back to all changes in this revision

Viewing changes to synti/stklib/Controller.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2004-02-07 15:18:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040207151822-es27xxkzbcxkebjm
Tags: 0.6.3-1
* New upstream version.
* Added patches:
  + [10_alsa_init_fix] New, from upstream CVS.
    Initialize direction variable when setting Alsa parameters.
  + [10_canvas_translation_fix] New, from upstream CVS.
    Do not translate tooltips twice in canvas popup.
  + [10_checkbox_fix] New, from upstream CVS.
    Use proper set/test methods on metronome checkboxes.
  + [10_html_doc_cleanup] New.
    Fix links and HTML errors in documentation.
  + [20_allow_system_timer] New.
    The new upstream version fails by default if the real-time clock
    could not be accessed (usually the case when not running suid-root).
    This patch reverts the old behaviour of falling back to the more
    inaccurate system timer.
* Updated patches:
  + [11_PIC_fixes_fixup] Rediffed.
* Removed patches:
  + [20_no_atomic_asm] Merged upstream.
* debian/compat: Splice out debhelper compatibility level from rules file.
* debian/control: Build-depend on latest jack release by default.
  Closes: #228788
* debian/control: Bump standards version.
* debian/control: Use auto-generated debconf dependency via misc:Depends.
* debian/control: Minor tweaks to the long description.
* debian/control: Tighten fluidsynth build dependency to sane version.
* debian/muse.doc-base: New. Register HTML documentation with doc-base.
* debian/templates: Tiny rewording, and typo fix.
* debian/templates, debian/po/*: Switch to po-debconf for translations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************/
2
 
/*
3
 
  Controller Class,
4
 
  by Gary P. Scavone, 2000
5
 
 
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.
13
 
 
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
20
 
  handled one.
21
 
 
22
 
  This class is primarily for use in STK
23
 
  main() event loops.
24
 
 
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.
35
 
*/
36
 
/******************************************/
37
 
 
38
 
#include "Controller.h"
39
 
 
40
 
Controller :: Controller(int inputMask)
41
 
{
42
 
  source = inputMask;
43
 
  default_ticks = RT_BUFFER_SIZE;
44
 
  msg_index = 0;
45
 
  num_messages = 0;
46
 
  score = new SKINI11();
47
 
 
48
 
#if defined(__STK_REALTIME_)
49
 
 
50
 
  maxfd = 0;
51
 
  char msg[256];
52
 
  struct sockaddr_in mysocket;
53
 
  FD_ZERO(&mask);
54
 
 
55
 
  /*
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().
59
 
  */
60
 
  for (int i=0; i<16; i++)
61
 
    fd[i] = 0;
62
 
 
63
 
  if ( source & STK_MIDI )
64
 
    midi_input = new RtMidi();
65
 
 
66
 
  /*
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 
73
 
     thread.
74
 
  */
75
 
  if (source) {
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)  {
81
 
#endif
82
 
      sprintf(msg, "Controller: unable to create stdin socket thread!\n");
83
 
      throw StkError(msg, StkError::PROCESS_THREAD);
84
 
    }
85
 
    source |= STK_SOCKET;
86
 
  }
87
 
 
88
 
  /* Let the user know that they can exit the program via the console
89
 
     if necessary.
90
 
  */
91
 
  if ( !(source & STK_PIPE) && inputMask )
92
 
    printf("\nType `Exit<cr>' to quit.\n\n");
93
 
 
94
 
  if ( source & STK_SOCKET ) {
95
 
    // Set up the socket server to accept remote connections
96
 
#if defined(__OS_Win_)  // Windoze-only stuff
97
 
    WSADATA wsaData;
98
 
    WORD wVersionRequested = MAKEWORD(1,1);
99
 
 
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);
104
 
    }
105
 
#endif
106
 
 
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);
112
 
    }
113
 
 
114
 
    mysocket.sin_family=AF_INET;
115
 
    mysocket.sin_addr.s_addr=INADDR_ANY;
116
 
    mysocket.sin_port=htons(STK_SOCKET_PORT);
117
 
 
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);
122
 
    }
123
 
 
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);
128
 
    }
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);
132
 
 
133
 
    FD_SET(local_socket, &mask);
134
 
    if (local_socket > maxfd) maxfd = local_socket;
135
 
  }
136
 
#endif // __STK_REALTIME
137
 
}
138
 
 
139
 
Controller :: ~Controller()
140
 
{
141
 
  delete score;
142
 
 
143
 
#if defined(__STK_REALTIME_)
144
 
 
145
 
  if ( source & STK_MIDI )
146
 
    delete midi_input;
147
 
 
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);
156
 
    WSACleanup();
157
 
#endif
158
 
  }
159
 
#endif // __STK_REALTIME
160
 
}
161
 
 
162
 
int Controller :: getType()
163
 
{
164
 
  return type;
165
 
}
166
 
 
167
 
MY_FLOAT Controller :: getByte2()
168
 
{
169
 
  return byte2;
170
 
}
171
 
 
172
 
MY_FLOAT Controller :: getByte3()
173
 
{
174
 
  return byte3;
175
 
}
176
 
 
177
 
MY_FLOAT Controller :: getChannel()
178
 
{
179
 
  return channel;
180
 
}
181
 
 
182
 
void Controller :: setDefaultTicks(long nSamples)
183
 
{
184
 
  default_ticks = nSamples;
185
 
}
186
 
 
187
 
int Controller :: getNextMessage()
188
 
{
189
 
#if defined(__STK_REALTIME_)
190
 
  static fd_set rmask;
191
 
  static struct timeval timeout = {0, 0};
192
 
  static int device = 0;
193
 
  static int nSockets = 0;
194
 
  static int fd_thread = 0;
195
 
  int checked = 0, i;
196
 
  char msg[256];
197
 
#endif
198
 
 
199
 
  // reset message type
200
 
  type = 0;
201
 
 
202
 
  if (!source) {
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 )
206
 
      return -1;
207
 
    goto have_message;
208
 
  }
209
 
 
210
 
#if defined(__STK_REALTIME_)
211
 
 
212
 
  if (num_messages > 0)
213
 
    goto have_message;
214
 
 
215
 
  while (checked < nSockets+1) {
216
 
 
217
 
    if ( source & STK_SOCKET ) {
218
 
 
219
 
      rmask = mask;
220
 
      if (select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout)) {
221
 
        // there is a file descriptor set
222
 
 
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);
230
 
          }
231
 
          if (nSockets != 0)
232
 
            // print message for connections subsequent to "piping" socket
233
 
            printf("New socket connection made.\n\n");
234
 
 
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);
241
 
#endif
242
 
 
243
 
          fd[nSockets] = remote_socket;
244
 
          if (nSockets == 0) fd_thread = remote_socket;
245
 
          nSockets++;
246
 
          FD_SET(remote_socket, &mask);
247
 
          if ( remote_socket > maxfd) maxfd = remote_socket;
248
 
          FD_CLR(local_socket, &rmask);
249
 
        }
250
 
 
251
 
 
252
 
 
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]);
258
 
            if (i == 0) {
259
 
              // the socket connection closed
260
 
              nSockets--;
261
 
              if ( nSockets == 0 )
262
 
                return -1;
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");
267
 
                  return 0;
268
 
                }
269
 
                else if (!(source & STK_PIPE) )
270
 
                  return -1;
271
 
              }
272
 
              if (device < nSockets) {
273
 
                // move descriptors down in the list
274
 
                for (int j=device; j<nSockets; j++)
275
 
                  fd[j] = fd[j+1];
276
 
              }
277
 
              device++;
278
 
              return 0;
279
 
            }
280
 
 
281
 
            device++;
282
 
 
283
 
            if ( !strncmp(message[msg_index], "Exit", 4) || !strncmp(message[msg_index], "exit", 4) ) {
284
 
              // we have an "Exit" message ... ignore it
285
 
              msg_index++;
286
 
              return 0;
287
 
            }
288
 
            // not an "Exit" message ... parse it
289
 
            goto have_message;
290
 
          }
291
 
          device++;
292
 
          if (++checked >= nSockets+1) break;
293
 
        }
294
 
      }
295
 
      else { // no file descriptors were set
296
 
        device += nSockets;
297
 
        checked += nSockets;
298
 
      }
299
 
    }
300
 
 
301
 
    // check MIDI 
302
 
    if (device >= nSockets) {
303
 
      //printf("got here, nSockets = %d, checked = %d, device = %d\n", nSockets, checked, device);
304
 
      device = 0;
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;
313
 
        }
314
 
      }
315
 
      if (++checked >= nSockets+1) break;
316
 
    }
317
 
  }
318
 
  // if we get here, we checked all devices but found no messages
319
 
  return default_ticks;
320
 
 
321
 
#endif // __STK_REALTIME
322
 
 
323
 
 have_message:
324
 
 
325
 
  //printf("%s", message[msg_index]);
326
 
  long ticks;
327
 
  score->parseThis(message[msg_index++]);
328
 
  num_messages--;
329
 
  if (msg_index >= MAX_MESSAGES) msg_index = 0;
330
 
  type = score->getType();
331
 
  if (type > 0) {
332
 
    MY_FLOAT temp = score->getDelta();
333
 
    if ( temp >= 0.0 )
334
 
      ticks = (long) (temp * SRATE);
335
 
    else
336
 
      // negative delta times specify realtime messages
337
 
      ticks = default_ticks;
338
 
 
339
 
    channel = score->getChannel();
340
 
    byte2 = score->getByteTwo();
341
 
    byte3 = score->getByteThree();
342
 
  }
343
 
  else {
344
 
    // Don't tick for comments or improperly formatted messages
345
 
    ticks = 0;
346
 
  }
347
 
 
348
 
  return ticks;
349
 
}
350
 
 
351
 
#if defined(__STK_REALTIME_)
352
 
 
353
 
int Controller :: parseSocketData(int fd)
354
 
{
355
 
  /*
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.
364
 
  */
365
 
 
366
 
  static char socket_buffer[MESSAGE_LENGTH];
367
 
  int index = 0, m = 0, bufsize = 0;
368
 
  int fill_msg;
369
 
 
370
 
  fill_msg = (msg_index + num_messages) % MAX_MESSAGES;
371
 
  memset(message[fill_msg], 0, MESSAGE_LENGTH);
372
 
 
373
 
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
374
 
  errno = 0;
375
 
  while (bufsize != -1 && errno != EAGAIN) {
376
 
#elif defined(__OS_Win_)
377
 
  while (bufsize != SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
378
 
#endif
379
 
    while (index < bufsize) {
380
 
      message[fill_msg][m++] = socket_buffer[index];
381
 
      if (socket_buffer[index++] == '\n') {
382
 
        m = 0;
383
 
        num_messages++;
384
 
        fill_msg = (msg_index + num_messages) % MAX_MESSAGES;
385
 
        memset(message[fill_msg], 0, MESSAGE_LENGTH);
386
 
      }
387
 
    }
388
 
    index = 0;
389
 
 
390
 
    // receive a new socket buffer
391
 
    memset(socket_buffer, 0, MESSAGE_LENGTH);
392
 
    bufsize = recv(fd, socket_buffer, MESSAGE_LENGTH, 0);
393
 
    if (bufsize == 0) {
394
 
      FD_CLR(fd, &mask);
395
 
#if defined(__OS_Win_)
396
 
      closesocket(fd);
397
 
#else
398
 
      close(fd);
399
 
#endif
400
 
      return 0;
401
 
    }
402
 
  }
403
 
 
404
 
  return 1;
405
 
}
406
 
 
407
 
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
408
 
 
409
 
void *stdinHandler(void *)
410
 
 
411
 
#elif defined(__OS_Win_)
412
 
 
413
 
void stdinHandler(void *)
414
 
 
415
 
#endif
416
 
{
417
 
  char message[MESSAGE_LENGTH];
418
 
  char msg[256];
419
 
  int local_socket;
420
 
  struct sockaddr_in server_address;
421
 
 
422
 
#if defined(__OS_Win_)  // Windoze-only stuff
423
 
  WSADATA wsaData;
424
 
  WORD wVersionRequested = MAKEWORD(1,1);
425
 
 
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);
430
 
  }
431
 
#endif
432
 
 
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);
438
 
  }
439
 
 
440
 
  struct hostent *hostp;
441
 
  hostp = gethostbyname("localhost");
442
 
 
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);
447
 
 
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);
453
 
      WSACleanup();
454
 
#else
455
 
      close(local_socket);
456
 
#endif
457
 
    sprintf(msg, "Controller: Couldn't connect stdin socket thread to server!\n");
458
 
    throw StkError(msg, StkError::PROCESS_SOCKET);
459
 
  }
460
 
 
461
 
  for (;;) {
462
 
    memset(message, 0, MESSAGE_LENGTH);
463
 
    if ( fgets(message, MESSAGE_LENGTH, stdin) == 0 )
464
 
      break;
465
 
    // check for an "Exit" message
466
 
    if ( !strncmp(message, "Exit", 4) || !strncmp(message, "exit", 4) )
467
 
      break;
468
 
 
469
 
    if (send(local_socket, (const char *)message, strlen(message), 0) < 0) {
470
 
#if defined(__OS_Win_)
471
 
      closesocket(local_socket);
472
 
      WSACleanup();
473
 
#else
474
 
      close(local_socket);
475
 
#endif
476
 
      sprintf(msg, "Controller: connection to socket server failed!\n");
477
 
      throw StkError(msg, StkError::PROCESS_SOCKET);
478
 
    }
479
 
  }
480
 
 
481
 
#if defined(__OS_Win_)
482
 
  closesocket(local_socket);
483
 
  _endthread();
484
 
#else
485
 
  close(local_socket);
486
 
  return NULL;
487
 
#endif
488
 
}
489
 
 
490
 
#endif // __STK_REALTIME