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

« back to all changes in this revision

Viewing changes to synti/stklib/RtMidi.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
 
  RtMidi.cpp
4
 
  Realtime MIDI I/O Object for STK,
5
 
  by Gary P. Scavone, 1998-2000.
6
 
  Based in part on code by Perry
7
 
  Cook (SGI), Paul Leonard (Linux),
8
 
  the RoseGarden team (Linux), and
9
 
  Bill Putnam (Win95/NT).
10
 
 
11
 
  At the moment, this object only
12
 
  handles MIDI input, though MIDI
13
 
  output code can go here when someone
14
 
  decides they need it (and writes it).
15
 
 
16
 
  This object opens a MIDI input device
17
 
  and parses MIDI messages into a MIDI
18
 
  buffer.  Time stamp info is converted
19
 
  to deltaTime. MIDI data is stored as
20
 
  MY_FLOAT to conform with SKINI.
21
 
 
22
 
  An optional argument to the constructor
23
 
  can be used to specify a device or card.
24
 
  When no argument is given, a default
25
 
  device is opened or a list of available
26
 
  devices is printed to allow selection
27
 
  by the user.
28
 
*/
29
 
/******************************************/
30
 
 
31
 
#include "RtMidi.h"
32
 
 
33
 
#if defined(__STK_REALTIME_)
34
 
 
35
 
#define MIDI_BUFFER_SIZE 1024
36
 
int writeOffset;
37
 
int readOffset;
38
 
 
39
 
#if defined(__OS_IRIX_)
40
 
 
41
 
/*************************************/
42
 
/*         SGI MIDI INPUT            */
43
 
/*************************************/
44
 
 
45
 
#include <pthread.h>
46
 
#include <dmedia/midi.h>
47
 
#include <sys/types.h>
48
 
#include <signal.h>
49
 
 
50
 
MDport inport;
51
 
 
52
 
MDevent *midiBuffer;
53
 
 
54
 
pthread_t midi_input_thread;
55
 
 
56
 
void *midiInputThread(void *)
57
 
{
58
 
  MDevent newMessage;
59
 
  int status;
60
 
 
61
 
  while (1) {
62
 
    mdReceive(inport, &newMessage, 1);
63
 
    status = (newMessage.msg[0] & MD_STATUSMASK);
64
 
    // Ignore all system messages
65
 
    if (status != 0xf0) {
66
 
      midiBuffer[writeOffset] = newMessage;
67
 
      writeOffset++;
68
 
 
69
 
      if( writeOffset >= MIDI_BUFFER_SIZE )
70
 
        writeOffset = 0;
71
 
    }
72
 
  }
73
 
}
74
 
 
75
 
RtMidi :: RtMidi(int device)
76
 
{
77
 
  int nports, card;
78
 
  char msg[256];
79
 
  char *device_name = 0;
80
 
 
81
 
  nports = mdInit();
82
 
  if (nports < 1) {
83
 
    sprintf(msg, "RtMidi: No SGI MIDI device available.\n");
84
 
    throw StkError(msg, StkError::MIDICARD_NOT_FOUND);
85
 
  }
86
 
 
87
 
  if (device == -1) {
88
 
    // open default MIDI interface
89
 
    inport = mdOpenInPort(NULL);
90
 
    if (inport == NULL) {
91
 
      sprintf(msg, "RtMidi: Cannot open default SGI MIDI device.\n");
92
 
      throw StkError(msg, StkError::MIDICARD_CONTROL);
93
 
    }
94
 
  }
95
 
  else {
96
 
    card = device;
97
 
    if ( (card < 0) || (card >= nports) ) {
98
 
      printf("\n");
99
 
      for (card=0; card<nports; card++) {
100
 
        device_name = mdGetName(card);
101
 
        printf("MIDI interface %d: %s\n", card, device_name);
102
 
      }
103
 
      char choice[16];
104
 
      printf("\nType a MIDI interface number from above: ");
105
 
      fgets(choice, 16, stdin);
106
 
      card = atoi(choice);
107
 
      printf("\n");
108
 
    }
109
 
    inport = mdOpenInPort(mdGetName(card));
110
 
    if (inport == NULL) {
111
 
      sprintf(msg, "RtMidi: Cannot open SGI MIDI interface %d.\n",
112
 
              card);
113
 
      throw StkError(msg, StkError::MIDICARD_CONTROL);
114
 
    }
115
 
  }
116
 
 
117
 
  mdSetStampMode(inport, MD_NOSTAMP);
118
 
 
119
 
  // Set up the circular buffer for the Midi Input Messages
120
 
  midiBuffer = new MDevent[MIDI_BUFFER_SIZE];
121
 
  readOffset = 0;
122
 
  writeOffset = 0;
123
 
 
124
 
  if (pthread_create(&midi_input_thread, NULL, midiInputThread, NULL)) {
125
 
    sprintf(msg, "RtMidi: unable to create MIDI input thread.\n");
126
 
    throw StkError(msg, StkError::PROCESS_THREAD);
127
 
  }
128
 
}
129
 
 
130
 
RtMidi :: ~RtMidi()
131
 
{
132
 
  pthread_cancel(midi_input_thread);
133
 
  pthread_join(midi_input_thread, NULL);
134
 
  mdClosePort(inport);
135
 
  delete [] midiBuffer;
136
 
}
137
 
 
138
 
int RtMidi ::  nextMessage()
139
 
{
140
 
  int status;
141
 
  int byte1;
142
 
  int byte2;
143
 
  MDevent lastEvent;
144
 
  static unsigned long long lastTimeStamp = 0;
145
 
 
146
 
  if ( readOffset == writeOffset ) return 0;
147
 
 
148
 
  lastEvent = midiBuffer[readOffset];
149
 
 
150
 
  readOffset++;
151
 
  if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
152
 
 
153
 
  status = (lastEvent.msg[0] & MD_STATUSMASK);
154
 
  byte1 = lastEvent.msg[1];
155
 
  byte2 = lastEvent.msg[2];
156
 
  channel = (lastEvent.msg[0] & MD_CHANNELMASK);
157
 
 
158
 
  if ((status == MD_PROGRAMCHANGE) ||
159
 
      (status == MD_CHANNELPRESSURE))
160
 
    {
161
 
      messageType = status;
162
 
      byteTwo = (float) byte1;
163
 
      deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
164
 
      lastTimeStamp = lastEvent.stamp;
165
 
    }
166
 
  else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) ||
167
 
           (status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE))
168
 
    {
169
 
      messageType = status;
170
 
      byteTwo = (float) byte1;
171
 
      byteThree = (float) byte2;
172
 
      deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
173
 
      lastTimeStamp = lastEvent.stamp;
174
 
    }
175
 
  else if (status == MD_PITCHBENDCHANGE)
176
 
    {
177
 
      messageType = status;
178
 
      byteTwo = (float) byte1 * NORM_7;
179
 
      byteTwo += (float) byte2;
180
 
      deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
181
 
      lastTimeStamp = lastEvent.stamp;
182
 
    }
183
 
  else
184
 
    {
185
 
      messageType = -1;
186
 
    }
187
 
 
188
 
  return messageType;
189
 
}
190
 
 
191
 
 
192
 
#elif ( defined(__OSS_API_) || defined(__ALSA_API_) )
193
 
 
194
 
/*************************************/
195
 
/*      OSS & ALSA MIDI INPUT        */
196
 
/*************************************/
197
 
 
198
 
#include <pthread.h>
199
 
#include <sys/time.h>
200
 
 
201
 
#if defined(__OSS_API_)
202
 
 
203
 
#include <fcntl.h>
204
 
#include <unistd.h>
205
 
#include <sys/ioctl.h>
206
 
#include <sys/types.h>
207
 
#include <linux/soundcard.h>
208
 
#include <errno.h>
209
 
int midi_in;
210
 
 
211
 
#else // ALSA_API
212
 
 
213
 
#include <sys/asoundlib.h>
214
 
snd_rawmidi_t *midi_in = 0;
215
 
 
216
 
#endif
217
 
 
218
 
typedef unsigned char byte;
219
 
 
220
 
/* MIDI System Messages */
221
 
#define MD_SYSTEM_MSG   ((byte)0xF0)
222
 
#define MD_PGM_CHANGE   ((byte)0xC0)
223
 
#define MD_CHN_PRESSURE   ((byte)0xD0)
224
 
#define MD_PITCH_BEND           ((byte)0xE0)
225
 
#define MessageType(MSG)  (byte)((MSG) & ((byte)0xF0))
226
 
 
227
 
typedef struct {
228
 
    byte data[3];
229
 
    float delta_time;
230
 
} MIDIMESSAGE;
231
 
 
232
 
MIDIMESSAGE *midiBuffer;
233
 
 
234
 
pthread_t midi_input_thread;
235
 
 
236
 
void *midiInputThread(void *)
237
 
{
238
 
  int numArgs = 2, argsLeft = 0;
239
 
  double lastTime = 0.0, newTime = 0.0;
240
 
  byte newByte;
241
 
  MIDIMESSAGE newMessage;
242
 
  int n;
243
 
  struct timeval tv;
244
 
 
245
 
  (void)gettimeofday(&tv, (struct timezone *)NULL);
246
 
  lastTime = (double) (tv.tv_sec + (tv.tv_usec * 0.000001));
247
 
 
248
 
  for (;;) {
249
 
 
250
 
#if defined(__OSS_API_)
251
 
 
252
 
    // Normally, you should check the return value of this read() call.
253
 
    // A return of -1 usually indicates an error.  However, for OSS
254
 
    // compatability in ALSA, we need to ignore such values.
255
 
 
256
 
    n = read(midi_in, &newByte, 1);
257
 
 
258
 
#else // ALSA_API
259
 
 
260
 
    if ((n = snd_rawmidi_read(midi_in, &newByte, 1)) == -1) {
261
 
      char msg[256];
262
 
      sprintf(msg, "RtMidi: Error reading ALSA raw MIDI device.\n");
263
 
      throw StkError(msg, StkError::MIDICARD_CAPS);
264
 
    }
265
 
 
266
 
#endif
267
 
 
268
 
    while (n > 0) {
269
 
      if (newByte & 0x80) { // status byte
270
 
        if (MessageType(newByte) == MD_SYSTEM_MSG) {
271
 
          n--;
272
 
          continue;
273
 
        }
274
 
        else if (MessageType(newByte) == MD_PGM_CHANGE ||
275
 
                 MessageType(newByte) == MD_CHN_PRESSURE) {
276
 
          numArgs = 1;
277
 
        }
278
 
        else {
279
 
          numArgs = 2;
280
 
        }
281
 
        newMessage.data[0] = newByte;
282
 
        newMessage.data[1] = 0;
283
 
        newMessage.data[2] = 0;
284
 
        argsLeft = numArgs;
285
 
      }
286
 
      else { // data byte
287
 
        if ( argsLeft == numArgs )
288
 
          newMessage.data[1] = newByte;
289
 
        else {
290
 
          newMessage.data[2] = newByte;
291
 
        }
292
 
        argsLeft--;
293
 
 
294
 
        if ( !argsLeft ) { // MIDI message complete
295
 
          // setup for running status mode (another event of the
296
 
          // same type without status byte)
297
 
          if (MessageType(newMessage.data[0]) == (int) MD_PGM_CHANGE ||
298
 
              MessageType(newMessage.data[0]) == (int) MD_CHN_PRESSURE) {
299
 
            argsLeft = 1;
300
 
          }
301
 
          else {
302
 
            argsLeft = 2;
303
 
          }
304
 
 
305
 
          // determine the delta time since the last event
306
 
          (void)gettimeofday(&tv, (struct timezone *)NULL);
307
 
          newTime = (double) ((double)tv.tv_sec + (((double)tv.tv_usec) * 0.000001));
308
 
          newMessage.delta_time = (float) (newTime - lastTime);
309
 
          lastTime = newTime;
310
 
 
311
 
          // Put newMessage in the circular buffer
312
 
          midiBuffer[writeOffset] = newMessage;
313
 
          writeOffset++;
314
 
 
315
 
          if( writeOffset >= MIDI_BUFFER_SIZE )
316
 
            writeOffset = 0;
317
 
        }
318
 
      }
319
 
      n--;
320
 
    }
321
 
  }
322
 
}
323
 
 
324
 
#if defined(__OSS_API_)
325
 
 
326
 
 
327
 
#define MAX_MIDI_DEVS 8
328
 
#define MIDI_NAME "/dev/cua/0"
329
 
 
330
 
RtMidi :: RtMidi(int device)
331
 
{
332
 
  int card = 0, err = 0, nChoices = 0;
333
 
  midi_in = 0;
334
 
  char msg[256];
335
 
  char device_name[16];
336
 
  bool print_list = FALSE;
337
 
 
338
 
  // /dev/midi should be a link to the default midi device under OSS
339
 
  strcpy(device_name, MIDI_NAME);
340
 
 
341
 
  // The OSS API doesn't really give us a means for probing the
342
 
  // capabilities of devices.  Thus, we'll just pursue a brute
343
 
  // force method of opening devices until we either find something
344
 
  // that doesn't complain or we have to give up.  We'll start with
345
 
  // the default device, then try /dev/midi00, /dev/midi01, etc...
346
 
 
347
 
  if (device != -1) {
348
 
    // check device specified as argument
349
 
    sprintf(device_name, "%s%d%d", MIDI_NAME, 0, device);
350
 
    // try to open this device
351
 
    if((midi_in = open(device_name, O_RDONLY, 0)) == -1)  {
352
 
      // Open device failed ... either busy or doesn't exist
353
 
      print_list = TRUE;
354
 
      printf("\n");
355
 
      card = 1;
356
 
    }
357
 
    else {
358
 
      goto have_good_device;
359
 
    }
360
 
  }
361
 
 
362
 
  while (card < MAX_MIDI_DEVS) {
363
 
    // if the default device doesn't work, try some others
364
 
    if (card > 0) sprintf(device_name, "%s%d%d", MIDI_NAME, 0, card-1);
365
 
 
366
 
    if ((midi_in = open(device_name, O_RDONLY, 0)) == -1)  {
367
 
      // Open device failed ... either busy or doesn't exist
368
 
      if (errno == EBUSY && print_list == FALSE)
369
 
        fprintf(stderr,"RtMidi: OSS MIDI device (%s) is busy and cannot be opened.\n",
370
 
                device_name);
371
 
      card++;
372
 
      continue;
373
 
    }
374
 
 
375
 
    if (print_list) {
376
 
      close(midi_in);
377
 
      printf("MIDI Card %d: %s\n", card-1, device_name);
378
 
      nChoices++;
379
 
      card++;
380
 
      continue;
381
 
    }
382
 
 
383
 
    // This device appears to be OK
384
 
    goto have_good_device;
385
 
  }
386
 
 
387
 
  if (print_list && nChoices) {
388
 
    char choice[16];
389
 
    printf("\nType a MIDI card number from above: ");
390
 
    fgets(choice, 16, stdin);
391
 
    card = atoi(choice);
392
 
    printf("\n");
393
 
    sprintf(device_name, "%s%d%d", MIDI_NAME, 0, card);
394
 
    if ((midi_in = open(device_name, O_RDONLY, 0)) == -1)  {
395
 
      sprintf(msg, "RtMidi: Unable to open OSS device (%s) for MIDI input!\n",
396
 
              device_name);
397
 
      throw StkError(msg, StkError::MIDICARD_CONTROL);
398
 
    }
399
 
    goto have_good_device;
400
 
  }
401
 
 
402
 
  // If we got here, no device was found to meet the requested functionality
403
 
  sprintf(msg, "RtMidi: no OSS device found for MIDI input!\n");
404
 
  throw StkError(msg, StkError::MIDICARD_CAPS);
405
 
 
406
 
 have_good_device: // the current device is what we will use
407
 
 
408
 
printf("oss midi device found\n");
409
 
 
410
 
  // Set up the circular buffer for the MIDI input messages
411
 
  midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
412
 
  readOffset = 0;
413
 
  writeOffset = 0;
414
 
 
415
 
      printf("create input thread\n");
416
 
  err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL);
417
 
  if (err) {
418
 
            printf("ERROR create thread\n");
419
 
            perror("mops");
420
 
    sprintf(msg, "RtMidi: unable to create MIDI input thread.\n");
421
 
    throw StkError(msg, StkError::PROCESS_THREAD);
422
 
  }
423
 
      else
424
 
            printf("allles OK!\n");
425
 
}
426
 
 
427
 
#else // ALSA_API
428
 
 
429
 
RtMidi :: RtMidi(int device)
430
 
{
431
 
  int err = 0, nChoices = 0;
432
 
  midi_in = 0;
433
 
  char msg[256];
434
 
  int card, dev;
435
 
  int default_card;
436
 
  bool print_list = FALSE;
437
 
  unsigned int mask;
438
 
  snd_ctl_t *chandle;
439
 
  struct snd_ctl_hw_info info;
440
 
        snd_rawmidi_info_t midiinfo;
441
 
 
442
 
  mask = snd_cards_mask();
443
 
  if (!mask) {
444
 
    sprintf(msg, "RtMidi: no ALSA sound/MIDI cards reported available.\n");
445
 
    throw StkError(msg, StkError::MIDICARD_NOT_FOUND);
446
 
  }
447
 
 
448
 
  if (device == -1) {
449
 
    default_card = snd_defaults_rawmidi_card();
450
 
  }
451
 
  else { // check device specified as argument
452
 
    if (!(mask & (1<<device))) {
453
 
      default_card = 0;
454
 
      print_list = TRUE;
455
 
      printf("\n");
456
 
    }
457
 
    else {
458
 
      default_card = device;
459
 
    }
460
 
  }
461
 
 
462
 
  card = default_card; // start with default card
463
 
  while (card<SND_CARDS) {
464
 
    if (mask & (1<<card)) {
465
 
      if ((err = snd_ctl_open(&chandle, card)) < 0) {
466
 
        fprintf(stderr,"RtMidi: ALSA error on control open (%d): %s\n",
467
 
                card, snd_strerror(err));
468
 
        continue;
469
 
      }
470
 
      if ((err = snd_ctl_hw_info(chandle, &info)) < 0) {
471
 
        fprintf(stderr,"RtMidi: ALSA error on control hardware info (%d): %s\n",
472
 
                card, snd_strerror(err));
473
 
        snd_ctl_close(chandle);
474
 
        continue;
475
 
      }
476
 
      for (dev=0; dev<(int)info.mididevs; dev++) {
477
 
        /* get information for each device */
478
 
        if ((err = snd_ctl_rawmidi_info(chandle, dev, &midiinfo)) < 0) {
479
 
          fprintf(stderr,"RtMidi: ALSA error on control MIDI info (%d): %s\n",
480
 
                  card, snd_strerror(err));
481
 
          continue;
482
 
        }
483
 
        if (midiinfo.flags & SND_RAWMIDI_INFO_INPUT) {
484
 
          // this device can handle MIDI input
485
 
          if (print_list) {
486
 
            printf("MIDI Card %d, Device %d: %s\n", card, dev, info.name);
487
 
            nChoices++;
488
 
            continue;
489
 
          }
490
 
          goto have_good_device;
491
 
        }
492
 
        else { // this device wont' work
493
 
          continue;
494
 
        }
495
 
      }
496
 
    }
497
 
    if (default_card == 0) card++;
498
 
    else { // default card != 0, now start with card 0 and keep searching
499
 
      if (card == default_card) card = 0; // first time only
500
 
      else {
501
 
        card++;
502
 
        if (card == default_card) card++; // skip over default card
503
 
      }
504
 
    }
505
 
  }
506
 
 
507
 
  if (print_list && nChoices) {
508
 
    char choice[16];
509
 
    printf("\nType a MIDI card number from above: ");
510
 
    fgets(choice, 16, stdin);
511
 
    card = atoi(choice);
512
 
    printf("Select a device for the same card: ");
513
 
    fgets(choice, 16, stdin);
514
 
    printf("\n");
515
 
    dev = atoi(choice);
516
 
    goto have_good_device;
517
 
  }
518
 
 
519
 
  // if we got here, no devices were found to meet the requested functionality
520
 
  sprintf(msg, "RtMidi: no ALSA device found for MIDI input!\n");
521
 
  throw StkError(msg, StkError::MIDICARD_CAPS);
522
 
 
523
 
 have_good_device: // the current value of card and dev are what we will use
524
 
 
525
 
  err = snd_rawmidi_open(&midi_in, card, dev, O_RDONLY);
526
 
  if (err) {
527
 
    sprintf(msg, "RtMidi: Error opening ALSA raw MIDI device: card %d, device %d.\n",
528
 
            card, dev);
529
 
    throw StkError(msg, StkError::MIDICARD_CONTROL);
530
 
  }
531
 
 
532
 
 
533
 
  // Set up the circular buffer for the MIDI input messages
534
 
  midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
535
 
  readOffset = 0;
536
 
  writeOffset = 0;
537
 
 
538
 
  err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL);
539
 
  if (err) {
540
 
    sprintf(msg, "RtMidi: unable to create MIDI input thread.\n");
541
 
    throw StkError(msg, StkError::PROCESS_THREAD);
542
 
  }
543
 
}
544
 
 
545
 
#endif
546
 
 
547
 
RtMidi :: ~RtMidi()
548
 
{
549
 
  pthread_cancel(midi_input_thread);
550
 
  delete [] midiBuffer;
551
 
#if defined(__OSS_API_)
552
 
  #if defined(__MIDIATOR_)
553
 
    tcdrain(midi_in);
554
 
  #endif
555
 
  if (midi_in != 0) close(midi_in);
556
 
#else // ALSA_API
557
 
  if (midi_in != 0)
558
 
    snd_rawmidi_close(midi_in);
559
 
#endif
560
 
}
561
 
 
562
 
int RtMidi::nextMessage()
563
 
{
564
 
  MIDIMESSAGE lastEvent;
565
 
 
566
 
  if ( readOffset == writeOffset ) return 0;
567
 
 
568
 
  lastEvent = midiBuffer[readOffset];
569
 
 
570
 
  readOffset++;
571
 
  if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
572
 
 
573
 
  messageType = (int) (lastEvent.data[0] & 0xf0);
574
 
  channel = (int) (lastEvent.data[0] & 0x0f);
575
 
  byteTwo = (float) lastEvent.data[1];
576
 
  if (messageType == (int) MD_PITCH_BEND)
577
 
    byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7);
578
 
  else
579
 
    byteThree = (float) lastEvent.data[2];
580
 
  deltaTime = (float) lastEvent.delta_time;
581
 
 
582
 
  return messageType;
583
 
}
584
 
 
585
 
#if defined(__MIDIATOR_)
586
 
 
587
 
void initializeMidiator()
588
 
{
589
 
  struct termios info;  /* serial port configuration info */
590
 
  int status; /* Serial port status */
591
 
  struct timeval tv;    /* to do a little time delay */
592
 
  char msg[256];
593
 
 
594
 
        /* Get the current serial port attributes, so we can change
595
 
         * the ones we care about.
596
 
   */
597
 
        if (tcgetattr(midi_in, &info) < 0) {
598
 
    sprintf(msg, "RtMidi: ioctl to get tty info failed (MIDIator support)!\n");
599
 
    throw StkError(msg, StkError::MIDICARD_CAPS);
600
 
        }
601
 
 
602
 
        bzero(&info, sizeof(info));
603
 
        info.c_cflag = BAUD_RATE | CRTSCTS | CS8 | CLOCAL | CREAD;
604
 
        info.c_iflag &= ~IGNCR;
605
 
        info.c_oflag &= ~IGNCR;
606
 
        
607
 
        /* set input mode (non-canonical, no echo,...) */
608
 
        info.c_lflag = 0;
609
 
        
610
 
        info.c_cc[VTIME]    = 1;   /* inter-character timer unused */
611
 
        info.c_cc[VMIN]     = 1;   /* blocking read until 5 chars received */
612
 
        
613
 
        tcflush(midi_in, TCIFLUSH);
614
 
 
615
 
        /* Set the attributes */
616
 
        tcsetattr(midi_in, TCSANOW, &info);
617
 
 
618
 
        /* Startup sequence, as per ron@MIDI_DEV's instructions */
619
 
        /* Many thanks to Ron for supporting Linux */
620
 
 
621
 
        /* Step 1 */
622
 
        /* Power down */
623
 
        /* deassert DTR and RTS */
624
 
        ioctl(midi_in, TIOCMGET, &status);
625
 
        status &= ~TIOCM_DTR;
626
 
        status &= ~TIOCM_RTS;
627
 
        ioctl(midi_in, TIOCMSET, status);
628
 
        /* Wait 600 ms to make sure everything is stable */
629
 
        tv.tv_sec = 0;
630
 
        tv.tv_usec = 600000;
631
 
        select(0, NULL, NULL, NULL, &tv);
632
 
 
633
 
  /* Step 2 */
634
 
  /* Power up */
635
 
  /* assert break */
636
 
        ioctl(midi_in, TIOCMGET, &status);
637
 
        status |= TCSBRK;
638
 
        ioctl(midi_in, TIOCMSET, status);
639
 
        /* Wait 300 ms to make sure everything is stable */
640
 
        tv.tv_sec = 0;
641
 
        tv.tv_usec = 300000;
642
 
        select(0, NULL, NULL, NULL, &tv);
643
 
 
644
 
        /* Step 3 */
645
 
        /* Set input mode */
646
 
        ioctl(midi_in, TIOCMGET, &status);
647
 
        status &= ~TIOCM_DTR;
648
 
        status |= TIOCM_RTS;
649
 
        ioctl(midi_in, TIOCMSET, status);
650
 
        /* Wait 40 us to make sure everything is stable */
651
 
        tv.tv_sec = 0;
652
 
        tv.tv_usec = 40;
653
 
        select(0, NULL, NULL, NULL, &tv);
654
 
 
655
 
        /* Step 4*/
656
 
        /* Set input mode */
657
 
        ioctl(midi_in, TIOCMGET, &status);
658
 
        status |= TIOCM_DTR;
659
 
        status &= TIOCM_RTS;
660
 
        ioctl(midi_in, TIOCMSET, status);
661
 
        /* Wait 40 us to make sure everything is stable */
662
 
        tv.tv_sec = 0;
663
 
        tv.tv_usec = 40;
664
 
        select(0, NULL, NULL, NULL, &tv);
665
 
 
666
 
        /* Step 5 */
667
 
        /* Set output mode */
668
 
        /* Bitval = RTS, clock = DTR */
669
 
 
670
 
  /* 1 */
671
 
        ioctl(midi_in, TIOCMGET, &status);
672
 
        status &= ~TIOCM_DTR; /* 0 */
673
 
        status |= TIOCM_RTS; /* 1 */
674
 
        ioctl(midi_in, TIOCMSET, status);
675
 
        /* Wait 40 us to make sure everything is stable */
676
 
        tv.tv_sec = 0;
677
 
        tv.tv_usec = 40;
678
 
        select(0, NULL, NULL, NULL, &tv);
679
 
        /****/
680
 
        ioctl(midi_in, TIOCMGET, &status);
681
 
        status |= TIOCM_DTR; /* 1 rising edge clock */
682
 
        status |= TIOCM_RTS; /* 1 */
683
 
        ioctl(midi_in, TIOCMSET, status);
684
 
        /* Wait 40 us to make sure everything is stable */
685
 
        tv.tv_sec = 0;
686
 
        tv.tv_usec = 40;
687
 
        select(0, NULL, NULL, NULL, &tv);
688
 
 
689
 
        /* 1 */
690
 
        ioctl(midi_in, TIOCMGET, &status);
691
 
        status &= ~TIOCM_DTR; /* 0 */
692
 
        status |= TIOCM_RTS; /* 1 */
693
 
        ioctl(midi_in, TIOCMSET, status);
694
 
        /* Wait 40 us to make sure everything is stable */
695
 
        tv.tv_sec = 0;
696
 
        tv.tv_usec = 40;
697
 
        select(0, NULL, NULL, NULL, &tv);
698
 
        /****/
699
 
        ioctl(midi_in, TIOCMGET, &status);
700
 
        status |= TIOCM_DTR; /* 1 rising edge clock */
701
 
        status |= TIOCM_RTS; /* 1 */
702
 
        ioctl(midi_in, TIOCMSET, status);
703
 
        /* Wait 40 us to make sure everything is stable */
704
 
        tv.tv_sec = 0;
705
 
        tv.tv_usec = 40;
706
 
        select(0, NULL, NULL, NULL, &tv);
707
 
 
708
 
        /* 0 */
709
 
        ioctl(midi_in, TIOCMGET, &status);
710
 
        status &= ~TIOCM_DTR; /* 0 */
711
 
        status &= ~TIOCM_RTS; /* 0 */
712
 
        ioctl(midi_in, TIOCMSET, status);
713
 
        /* Wait 40 us to make sure everything is stable */
714
 
        tv.tv_sec = 0;
715
 
        tv.tv_usec = 40;
716
 
        select(0, NULL, NULL, NULL, &tv);
717
 
        /****/
718
 
        ioctl(midi_in, TIOCMGET, &status);
719
 
        status |= TIOCM_DTR; /* 1 rising edge clock */
720
 
        status &= ~TIOCM_RTS; /* 0 */
721
 
        ioctl(midi_in, TIOCMSET, status);
722
 
        /* Wait 40 us to make sure everything is stable */
723
 
        tv.tv_sec = 0;
724
 
        tv.tv_usec = 40;
725
 
        select(0, NULL, NULL, NULL, &tv);
726
 
 
727
 
        /* Step 6 ... necessary ?*/
728
 
        /* Set RTS=0,DTR=1 ... but they already are from previous ^ */
729
 
        /****/
730
 
        ioctl(midi_in, TIOCMGET, &status);
731
 
        status |= TIOCM_DTR; /* 1 rising edge clock */
732
 
        status &= ~TIOCM_RTS; /* 0 */
733
 
        ioctl(midi_in, TIOCMSET, status);
734
 
        /* Wait 40 us to make sure everything is stable */
735
 
        tv.tv_sec = 0;
736
 
        tv.tv_usec = 40;
737
 
        select(0, NULL, NULL, NULL, &tv);
738
 
 
739
 
  /* Step 7 */
740
 
  /* Deassert break */
741
 
        ioctl(midi_in, TIOCMGET, &status);
742
 
        status &= ~TCSBRK;
743
 
        ioctl(midi_in, TIOCMSET, status);
744
 
        /* Wait 100 ms to make sure everything is stable */
745
 
        tv.tv_sec = 0;
746
 
        tv.tv_usec = 100000;
747
 
        select(0, NULL, NULL, NULL, &tv);
748
 
  /*  End Midiator startup sequence -- midi_dev_type = MIDIATOR */
749
 
}
750
 
#endif // MIDIator
751
 
 
752
 
#elif defined(__OS_Win_)
753
 
 
754
 
/*************************************/
755
 
/*        Windoze MIDI INPUT         */
756
 
/*************************************/
757
 
 
758
 
#define MIDI_NOTEON 0x90
759
 
#define MIDI_NOTEOFF 0x80
760
 
#define MIDI_POLYKEYPRESSURE 0xA0
761
 
#define MIDI_CHANNELPRESSURE 0xD0
762
 
#define MIDI_PROGRAMCHANGE 0xC0
763
 
#define MIDI_CONTROLCHANGE 0xB0
764
 
#define MIDI_PITCHBEND 0xE0
765
 
 
766
 
typedef struct {
767
 
    DWORD data;
768
 
    DWORD time;
769
 
} MIDIMESSAGE;
770
 
 
771
 
MIDIMESSAGE *midiBuffer;
772
 
 
773
 
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
774
 
                        DWORD instancePtr, DWORD midiMessage, DWORD timestamp)
775
 
{
776
 
  MIDIMESSAGE newMessage;
777
 
                        
778
 
  switch (inputStatus) {
779
 
 
780
 
  case MIM_DATA:
781
 
 
782
 
    // Ignore Active Sensing messages
783
 
    if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
784
 
      break;
785
 
    }
786
 
    newMessage.data = midiMessage;
787
 
    newMessage.time = timestamp;
788
 
 
789
 
    // Put newMessage in the circular buffer
790
 
    midiBuffer[writeOffset] = newMessage;
791
 
    writeOffset++;
792
 
 
793
 
    if( writeOffset >= MIDI_BUFFER_SIZE )
794
 
      writeOffset = 0;
795
 
    break;
796
 
 
797
 
  default:
798
 
    break;
799
 
  }
800
 
}
801
 
 
802
 
HMIDIIN hMidiIn ;   // Handle to Midi Output Device
803
 
 
804
 
RtMidi :: RtMidi(int device)
805
 
{
806
 
  MMRESULT result;
807
 
  UINT uDeviceID;
808
 
  MIDIINCAPS deviceCaps;
809
 
  UINT i;
810
 
  char msg[256];
811
 
 
812
 
  uDeviceID = midiInGetNumDevs();
813
 
  if (uDeviceID < 1) {
814
 
    sprintf(msg, "RtMidi: No windoze MIDI device available.\n");
815
 
    throw StkError(msg, StkError::MIDICARD_NOT_FOUND);
816
 
  }
817
 
 
818
 
  /* Our normal scheme is to use the default device if no argument
819
 
     is supplied to RtMidi() or if the argument = -1.  However,
820
 
     there is no way to specify a default MIDI device under windoze.
821
 
     So, I'm going to print the list if device = -1.
822
 
  */
823
 
  if ( (device != -1) && (device < uDeviceID) ) {
824
 
                // try to open device specified as argument
825
 
                result = midiInOpen(&hMidiIn, device,
826
 
                                                                                                (DWORD)&midiInputCallback,
827
 
                                                                                                (DWORD)NULL,
828
 
                                                                                                CALLBACK_FUNCTION);
829
 
                if (result == MMSYSERR_NOERROR)
830
 
      goto have_good_device;
831
 
  }
832
 
 
833
 
  printf("\nMIDI input interfaces available: %i\n",uDeviceID);
834
 
  for (i=0; i<uDeviceID; i++) {
835
 
    result = midiInGetDevCaps(i, &deviceCaps, sizeof(MIDIINCAPS));
836
 
    printf("   MIDI interface %d is %s\n", i, deviceCaps.szPname);
837
 
  }
838
 
 
839
 
  if (uDeviceID > 1) {
840
 
    char choice[16];
841
 
    printf("\nType the MIDI interface to open: ");
842
 
    fgets(choice, 16, stdin);
843
 
    uDeviceID = (UINT) atoi(choice);
844
 
  }
845
 
  else uDeviceID -= 1;
846
 
 
847
 
  // Open the port and return any errors        
848
 
  result = midiInOpen(&hMidiIn, uDeviceID,
849
 
                                                                                        (DWORD)&midiInputCallback,
850
 
                                                                                        (DWORD)NULL,
851
 
                                                                                        CALLBACK_FUNCTION);
852
 
  if (result != MMSYSERR_NOERROR) {
853
 
    sprintf(msg, "RtMidi: Cannot open Windoze MIDI interface %d.\n",
854
 
            uDeviceID);
855
 
    throw StkError(msg, StkError::MIDICARD_CONTROL);
856
 
  }
857
 
 
858
 
 have_good_device: // the current device is what we will use
859
 
 
860
 
  // Set up the circular buffer for the Midi Input Messages
861
 
  midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
862
 
  readOffset = 0;
863
 
  writeOffset = 0;
864
 
        
865
 
  midiInStart( hMidiIn );
866
 
}
867
 
 
868
 
RtMidi :: ~RtMidi()
869
 
{
870
 
  midiInReset( hMidiIn );
871
 
  midiInStop( hMidiIn );
872
 
  midiInClose( hMidiIn );
873
 
  delete [] midiBuffer;
874
 
}
875
 
 
876
 
int RtMidi ::  nextMessage()
877
 
{
878
 
  int status;
879
 
  int byte1;
880
 
  int byte2;
881
 
  MIDIMESSAGE lastEvent;
882
 
  static DWORD lastTime = 0;
883
 
  static DWORD newTime = 0;
884
 
 
885
 
  if ( readOffset == writeOffset ) return 0;
886
 
 
887
 
  lastEvent = midiBuffer[readOffset];
888
 
                
889
 
  readOffset++;
890
 
  if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
891
 
 
892
 
  status = (int) (lastEvent.data & 0xff);
893
 
  byte1 = (int) (lastEvent.data & 0xff00) >> 8;
894
 
  byte2 = (int) (lastEvent.data & 0xff0000) >> 16;
895
 
  channel = (int) (status & 0x0f);
896
 
  status &= 0xf0;     // Clear lower byte of status
897
 
  newTime = lastEvent.time;
898
 
  deltaTime = (float) (newTime - lastTime) * 0.001;
899
 
  lastTime = newTime;
900
 
 
901
 
  if ((status == MIDI_PROGRAMCHANGE) ||
902
 
                        (status == MIDI_CHANNELPRESSURE))
903
 
                {
904
 
                        messageType = status;
905
 
                        byteTwo = (float) byte1;
906
 
                }
907
 
  else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) ||
908
 
                                         (status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE))
909
 
                {
910
 
                        messageType = status;
911
 
                        byteTwo = (float) byte1;
912
 
                        byteThree = (float) byte2;
913
 
                }
914
 
  else if (status == MIDI_PITCHBEND)
915
 
                {
916
 
                        messageType = status;
917
 
                        byteTwo = (float) (byte1 * NORM_7);
918
 
                        byteTwo += (float) byte2;
919
 
                }
920
 
  else
921
 
                {
922
 
                        messageType = -1;
923
 
                }
924
 
 
925
 
  return messageType;
926
 
}
927
 
 
928
 
#endif
929
 
 
930
 
void RtMidi :: printMessage()
931
 
{
932
 
  printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n",
933
 
                 this->getType(), this->getChannel(), this->getByteTwo(),
934
 
                 this->getByteThree());
935
 
}
936
 
 
937
 
int RtMidi ::  getType()
938
 
{
939
 
  return messageType;
940
 
}
941
 
 
942
 
int RtMidi ::  getChannel()
943
 
{
944
 
  return channel;
945
 
}
946
 
 
947
 
MY_FLOAT RtMidi :: getByteTwo()
948
 
{
949
 
  return byteTwo;
950
 
}
951
 
 
952
 
MY_FLOAT RtMidi :: getByteThree()
953
 
{
954
 
  return byteThree;
955
 
}
956
 
 
957
 
MY_FLOAT RtMidi :: getDeltaTime()
958
 
{
959
 
  return deltaTime;
960
 
}
961
 
 
962
 
 
963
 
#endif