Browse Source

Version 1.0.0

Gary Scavone 11 years ago
commit
eeca354081

+ 57 - 0
RtError.h

@@ -0,0 +1,57 @@
+/************************************************************************/
+/*! \class RtError
+    \brief Exception handling class for RtAudio & RtMidi.
+
+    The RtError class is quite simple but it does allow errors to be
+    "caught" by RtError::Type. See the RtAudio and RtMidi
+    documentation to know which methods can "throw" an RtError.
+
+*/
+/************************************************************************/
+
+#ifndef RTERROR_H
+#define RTERROR_H
+
+#include <iostream>
+#include <string>
+
+class RtError
+{
+public:
+  //! Defined RtError types.
+  enum Type {
+    WARNING,
+    DEBUG_WARNING,
+    UNSPECIFIED,
+    NO_DEVICES_FOUND,
+    INVALID_DEVICE,
+    INVALID_STREAM,
+    MEMORY_ERROR,
+    INVALID_PARAMETER,
+    DRIVER_ERROR,
+    SYSTEM_ERROR,
+    THREAD_ERROR
+  };
+
+protected:
+  std::string message_;
+  Type type_;
+
+public:
+  //! The constructor.
+  RtError(const std::string& message, Type type = RtError::UNSPECIFIED) : message_(message), type_(type) {}
+
+  //! The destructor.
+  virtual ~RtError(void) {}
+
+  //! Prints "thrown" error message to stdout.
+  virtual void printMessage(void) { std::cout << '\n' << message_ << "\n\n"; }
+
+  //! Returns the "thrown" error message type.
+  virtual const Type& getType(void) { return type_; }
+
+  //! Returns the "thrown" error message string.
+  virtual const std::string& getMessage(void) { return message_; }
+};
+
+#endif

+ 1973 - 0
RtMidi.cpp

@@ -0,0 +1,1973 @@
+/**********************************************************************/
+/*! \class RtMidi
+    \brief An abstract base class for realtime MIDI input/output.
+
+    This class implements some common functionality for the realtime
+    MIDI input/output subclasses RtMidiIn and RtMidiOut.
+
+    RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
+
+    RtMidi: realtime MIDI i/o C++ classes
+    Copyright (c) 2003-2004 Gary P. Scavone
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation files
+    (the "Software"), to deal in the Software without restriction,
+    including without limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of the Software,
+    and to permit persons to whom the Software is furnished to do so,
+    subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    Any person wishing to distribute modifications to the Software is
+    requested to send the modifications to the original developer so that
+    they can be incorporated into the canonical version.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+/**********************************************************************/
+
+// RtMidi: Version 1.0.0, 17 September 2004
+
+#include "RtMidi.h"
+#include <sstream>
+
+//*********************************************************************//
+//  Common RtMidi Definitions
+//*********************************************************************//
+
+RtMidi :: RtMidi()
+  : apiData_( 0 ), connected_( false )
+{
+}
+
+void RtMidi :: error( RtError::Type type )
+{
+  if (type == RtError::WARNING) {
+    std::cerr << '\n' << errorString_ << "\n\n";
+  }
+  else if (type == RtError::DEBUG_WARNING) {
+#if defined(__RTMIDI_DEBUG__)
+    std::cerr << '\n' << errorString_ << "\n\n";
+#endif
+  }
+  else {
+    std::cerr << '\n' << errorString_ << "\n\n";
+    throw RtError( errorString_, type );
+  }
+}
+
+//*********************************************************************//
+//  Common RtMidiIn Definitions
+//*********************************************************************//
+
+RtMidiIn :: RtMidiIn() : RtMidi()
+{
+  this->initialize();
+}
+
+void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData )
+{
+  if ( inputData_.usingCallback ) {
+    errorString_ = "RtMidiIn::setCallback: a callback function is already set!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  if ( !callback ) {
+    errorString_ = "RtMidiIn::setCallback: callback function value is invalid!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  inputData_.userCallback = (void *) callback;
+  inputData_.userData = userData;
+  inputData_.usingCallback = true;
+}
+
+void RtMidiIn :: cancelCallback()
+{
+  if ( !inputData_.usingCallback ) {
+    errorString_ = "RtMidiIn::cancelCallback: no callback function was set!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  inputData_.userCallback = 0;
+  inputData_.userData = 0;
+  inputData_.usingCallback = false;
+}
+
+void RtMidiIn :: setQueueSizeLimit( unsigned int queueSize )
+{
+  inputData_.queueLimit = queueSize;
+}
+
+void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense )
+{
+  inputData_.ignoreFlags = 0;
+  if ( midiSysex ) inputData_.ignoreFlags = 0x01;
+  if ( midiTime ) inputData_.ignoreFlags |= 0x02;
+  if ( midiSense ) inputData_.ignoreFlags |= 0x04;
+}
+
+double RtMidiIn :: getMessage( std::vector<unsigned char> *message )
+{
+  message->clear();
+
+  if ( inputData_.usingCallback ) {
+    errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port.";
+    error( RtError::WARNING );
+    return 0.0;
+  }
+
+  if ( inputData_.queue.size() == 0 ) return 0.0;
+
+  // Copy queued message to the vector pointer argument and then "pop" it.
+  std::vector<unsigned char> *bytes = &(inputData_.queue.front().bytes);
+  message->assign( bytes->begin(), bytes->end() );
+  double deltaTime = inputData_.queue.front().timeStamp;
+  inputData_.queue.pop();
+
+  return deltaTime;
+}
+
+//*********************************************************************//
+//  Common RtMidiOut Definitions
+//*********************************************************************//
+
+RtMidiOut :: RtMidiOut() : RtMidi()
+{
+  this->initialize();
+}
+
+
+//*********************************************************************//
+//  API: Macintosh OS-X
+//*********************************************************************//
+
+// API information found at:
+//   - http://developer. apple .com/audio/pdf/coreaudio.pdf 
+
+#if defined(__MACOSX_CORE__)
+
+// The CoreMIDI API is based on the use of a callback function for
+// MIDI input.  We convert the system specific time stamps to delta
+// time values.
+
+// OS-X CoreMIDI header files.
+#include <CoreMIDI/CoreMIDI.h>
+#include <CoreAudio/HostTime.h>
+
+// A structure to hold variables related to the CoreMIDI API
+// implementation.
+struct CoreMidiData {
+  MIDIClientRef client;
+  MIDIPortRef port;
+  MIDIEndpointRef endpoint;
+  MIDIEndpointRef destinationId;
+  unsigned long long lastTime;
+};
+
+//*********************************************************************//
+//  API: OS-X
+//  Class Definitions: RtMidiIn
+//*********************************************************************//
+
+void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef )
+{
+  RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (procRef);
+  CoreMidiData *apiData = static_cast<CoreMidiData *> (data->apiData);
+
+  bool continueSysex = false;
+  unsigned char status;
+  unsigned short nBytes, iByte, size;
+  unsigned long long time;
+  RtMidiIn::MidiMessage message;
+  const MIDIPacket *packet = &list->packet[0];
+  for ( unsigned int i=0; i<list->numPackets; ++i ) {
+
+    // My interpretation of the CoreMIDI documentation: all message
+    // types, except sysex, are complete within a packet and there may
+    // be several of them in a single packet.  Sysex messages can be
+    // broken across multiple packets but are bundled alone within a
+    // packet.  I'm assuming that sysex messages, if segmented, must
+    // be complete within the same MIDIPacketList.
+
+    nBytes = packet->length;
+    if ( nBytes == 0 ) continue;
+
+    // Calculate time stamp.
+    message.timeStamp = 0.0;
+    if ( data->firstMessage )
+      data->firstMessage = false;
+    else {
+      time = packet->timeStamp;
+      time -= apiData->lastTime;
+      time = AudioConvertHostTimeToNanos( time );
+      message.timeStamp = time * 0.000000001;
+    }
+    apiData->lastTime = packet->timeStamp;
+
+    iByte = 0;
+    if ( continueSysex ) {
+      // We have a continuing, segmented sysex message.
+      if ( !(data->ignoreFlags & 0x01) ) {
+        // If we're not ignoring sysex messages, copy the entire packet.
+        for ( unsigned int j=0; j<nBytes; j++ )
+          message.bytes.push_back( packet->data[j] );
+      }
+      if ( packet->data[nBytes] == 0xF7 ) continueSysex = false;
+      if ( !continueSysex ) {
+        // If not a continuing sysex message, invoke the user callback function or queue the message.
+        if ( data->usingCallback && message.bytes.size() > 0 ) {
+          RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+          callback( message.timeStamp, &message.bytes, data->userData );
+        }
+        else {
+          // As long as we haven't reached our queue size limit, push the message.
+          if ( data->queueLimit > data->queue.size() )
+            data->queue.push( message );
+          else
+            std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+        }
+        message.bytes.clear();
+      }
+    }
+    else {
+      while ( iByte < nBytes ) {
+        size = 0;
+        // We are expecting that the next byte in the packet is a status byte.
+        status = packet->data[iByte];
+        if ( !(status & 0x80) ) break;
+        // Determine the number of bytes in the MIDI message.
+        if ( status < 0xC0 ) size = 3;
+        else if ( status < 0xE0 ) size = 2;
+        else if ( status < 0xF0 ) size = 3;
+        else if ( status == 0xF0 ) {
+          // A MIDI sysex
+          if ( data->ignoreFlags & 0x01 ) {
+            size = 0;
+            iByte = nBytes;
+          }
+          else size = nBytes - iByte;
+          if ( packet->data[nBytes] == 0xF7 ) continueSysex = false;
+        }
+        else if ( status < 0xF3 ) {
+          if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) {
+            // A MIDI time code message and we're ignoring it.
+            size = 0;
+            iByte += 3;
+          }
+          else size = 3;
+        }
+        else if ( status == 0xF3 ) size = 2;
+        else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
+          // A MIDI active sensing message and we're ignoring it.
+          size = 0;
+          iByte += 1;
+        }
+        else size = 1;
+
+        // Copy the MIDI data to our vector.
+        if ( size ) {
+          message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] );
+          if ( !continueSysex ) {
+            // If not a continuing sysex message, invoke the user callback function or queue the message.
+            if ( data->usingCallback ) {
+              RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+              callback( message.timeStamp, &message.bytes, data->userData );
+            }
+            else {
+              // As long as we haven't reached our queue size limit, push the message.
+              if ( data->queueLimit > data->queue.size() )
+                data->queue.push( message );
+              else
+                std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+            }
+            message.bytes.clear();
+          }
+          iByte += size;
+        }
+      }
+    }
+    packet = MIDIPacketNext(packet);
+  }
+}
+
+void RtMidiIn :: initialize( void )
+{
+  // Set up our client.
+  MIDIClientRef client;
+  OSStatus result = MIDIClientCreate( CFSTR("RtMidi Input Client"), NULL, NULL, &client );
+  if ( result != noErr ) {
+    errorString_ = "RtMidiIn::initialize: error creating OS-X MIDI client object.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific connection information.
+  CoreMidiData *data = (CoreMidiData *) new CoreMidiData;
+  data->client = client;
+  data->endpoint = 0;
+  apiData_ = (void *) data;
+  inputData_.apiData = (void *) data;
+}
+
+void RtMidiIn :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nSrc = MIDIGetNumberOfSources();
+  if (nSrc < 1) {
+    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nSrc ) {
+    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  MIDIPortRef port;
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+  OSStatus result = MIDIInputPortCreate( data->client, CFSTR("RtMidi MIDI Input Port"), midiInputCallback, (void *)&inputData_, &port );
+  if ( result != noErr ) {
+    MIDIClientDispose( data->client );
+    errorString_ = "RtMidiIn::openPort: error creating OS-X MIDI input port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Get the desired input source identifier.
+  MIDIEndpointRef endpoint = MIDIGetSource( portNumber );
+  if ( endpoint == NULL ) {
+    MIDIPortDispose( port );
+    MIDIClientDispose( data->client );
+    errorString_ = "RtMidiIn::openPort: error getting MIDI input source reference.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Make the connection.
+  result = MIDIPortConnectSource( port, endpoint, NULL );
+  if ( result != noErr ) {
+    MIDIPortDispose( port );
+    MIDIClientDispose( data->client );
+    errorString_ = "RtMidiIn::openPort: error connecting OS-X MIDI input port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific port information.
+  data->port = port;
+
+  connected_ = true;
+}
+
+void RtMidiIn :: openVirtualPort()
+{
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+
+  // Create a virtual MIDI input destination.
+  MIDIEndpointRef endpoint;
+  OSStatus result = MIDIDestinationCreate( data->client, CFSTR("RtMidi Input"), midiInputCallback, (void *)&inputData_, &endpoint );
+  if ( result != noErr ) {
+    errorString_ = "RtMidiIn::openVirtualPort: error creating virtual OS-X MIDI destination.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific connection information.
+  data->endpoint = endpoint;
+}
+
+void RtMidiIn :: closePort( void )
+{
+  if ( connected_ ) {
+    CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+    MIDIPortDispose( data->port );
+    connected_ = false;
+  }
+}
+
+RtMidiIn :: ~RtMidiIn()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+  MIDIClientDispose( data->client );
+  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );
+  delete data;
+}
+
+unsigned int RtMidiIn :: getPortCount()
+{
+  return MIDIGetNumberOfSources();
+}
+
+std::string RtMidiIn :: getPortName( unsigned int portNumber )
+{
+  CFStringRef nameRef;
+  MIDIEndpointRef portRef;
+  std::ostringstream ost;
+  char name[128];
+
+  if ( portNumber >= MIDIGetNumberOfSources() ) {
+    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+  portRef = MIDIGetSource( portNumber );
+
+  MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef );
+  CFStringGetCString( nameRef, name, sizeof(name), 0);
+  CFRelease( nameRef );
+  std::string stringName = name;
+  return stringName;
+}
+
+//*********************************************************************//
+//  API: OS-X
+//  Class Definitions: RtMidiOut
+//*********************************************************************//
+
+unsigned int RtMidiOut :: getPortCount()
+{
+  return MIDIGetNumberOfDestinations();
+}
+
+std::string RtMidiOut :: getPortName( unsigned int portNumber )
+{
+  CFStringRef nameRef;
+  MIDIEndpointRef portRef;
+  std::ostringstream ost;
+  char name[128];
+
+  if ( portNumber >= MIDIGetNumberOfDestinations() ) {
+    ost << "RtMidiOut::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+  portRef = MIDIGetDestination( portNumber );
+
+  MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef );
+  CFStringGetCString( nameRef, name, sizeof(name), 0);
+  CFRelease( nameRef );
+  std::string stringName = name;
+  return stringName;
+}
+
+void RtMidiOut :: initialize( void )
+{
+  // Set up our client.
+  MIDIClientRef client;
+  OSStatus result = MIDIClientCreate( CFSTR("RtMidi Output Client"), NULL, NULL, &client );
+  if ( result != noErr ) {
+    errorString_ = "RtMidiOut::initialize: error creating OS-X MIDI client object.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific connection information.
+  CoreMidiData *data = (CoreMidiData *) new CoreMidiData;
+  data->client = client;
+  data->endpoint = 0;
+  apiData_ = (void *) data;
+}
+
+void RtMidiOut :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiOut::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nDest = MIDIGetNumberOfDestinations();
+  if (nDest < 1) {
+    errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nDest ) {
+    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  MIDIPortRef port;
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+  OSStatus result = MIDIOutputPortCreate( data->client, CFSTR("RtMidi Virtual MIDI Output Port"), &port );
+  if ( result != noErr ) {
+    MIDIClientDispose( data->client );
+    errorString_ = "RtMidiOut::openPort: error creating OS-X MIDI output port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Get the desired output port identifier.
+  MIDIEndpointRef destination = MIDIGetDestination( portNumber );
+  if ( destination == NULL ) {
+    MIDIPortDispose( port );
+    MIDIClientDispose( data->client );
+    errorString_ = "RtMidiOut::openPort: error getting MIDI output destination reference.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific connection information.
+  data->port = port;
+  data->destinationId = destination;
+  connected_ = true;
+}
+
+void RtMidiOut :: closePort( void )
+{
+  if ( connected_ ) {
+    CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+    MIDIPortDispose( data->port );
+    connected_ = false;
+  }
+}
+
+void RtMidiOut :: openVirtualPort()
+{
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+
+  if ( data->endpoint ) {
+    errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  // Create a virtual MIDI output source.
+  MIDIEndpointRef endpoint;
+  OSStatus result = MIDISourceCreate( data->client, CFSTR("RtMidi Output"), &endpoint );
+  if ( result != noErr ) {
+    errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  // Save our api-specific connection information.
+  data->endpoint = endpoint;
+}
+
+RtMidiOut :: ~RtMidiOut()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+  MIDIClientDispose( data->client );
+  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );
+  delete data;
+}
+
+void RtMidiOut :: sendMessage( std::vector<unsigned char> *message )
+{
+  unsigned int nBytes = message->size();
+  // Pad the buffer for extra (unknown) structure data.
+  Byte buffer[nBytes+32];
+  MIDIPacketList *pktlist = (MIDIPacketList *) buffer;
+  MIDIPacket *curPacket = MIDIPacketListInit( pktlist );
+
+  MIDITimeStamp timeStamp = 0;
+  curPacket = MIDIPacketListAdd( pktlist, sizeof(buffer), curPacket, timeStamp, nBytes, &message->at(0) );
+
+  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
+
+  // Send to any destinations that may have connected to us.
+  OSStatus result;
+  if ( data->endpoint ) {
+    result = MIDIReceived( data->endpoint, pktlist );
+    if ( result != noErr ) {
+      errorString_ = "RtMidiOut::sendMessage: error sending MIDI to virtual destinations.";
+      error( RtError::WARNING );
+    }
+  }
+
+  // And send to an explicit destination port if we're connected.
+  if ( connected_ ) {
+    result = MIDISend( data->port, data->destinationId, pktlist );
+    if ( result != noErr ) {
+      errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port.";
+      error( RtError::WARNING );
+    }
+  }
+}
+
+#endif  // __MACOSX_CORE__
+
+
+//*********************************************************************//
+//  API: LINUX ALSA
+//*********************************************************************//
+
+// API information found at:
+//   - http://www.alsa-project.org/documentation.php#Library
+
+#if defined(__LINUX_ALSA__)
+
+// The ALSA Sequencer API is based on the use of a callback function for
+// MIDI input.  We convert the system specific time stamps to delta
+// time values.
+
+#include <pthread.h>
+#include <sys/time.h>
+
+// ALSA header file.
+#include <alsa/asoundlib.h>
+
+// A structure to hold variables related to the ALSA API
+// implementation.
+struct AlsaMidiData {
+  snd_seq_t *seq;
+  int vport;
+  snd_seq_port_subscribe_t *subscription;
+  snd_midi_event_t *coder;
+  unsigned int bufferSize;
+  unsigned char *buffer;
+  pthread_t thread;
+  unsigned long long lastTime;
+};
+
+#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
+
+//*********************************************************************//
+//  API: LINUX ALSA
+//  Class Definitions: RtMidiIn
+//*********************************************************************//
+
+extern "C" void *alsaMidiHandler( void *ptr )
+{
+  RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (ptr);
+  AlsaMidiData *apiData = static_cast<AlsaMidiData *> (data->apiData);
+
+  long nBytes;
+  unsigned long long time, lastTime;
+  unsigned char lastStatus = 0;
+  RtMidiIn::MidiMessage message;
+
+  snd_seq_event_t *ev;
+  struct timeval tv;
+  int result;
+  apiData->bufferSize = 32;
+  result = snd_midi_event_new( 0, &apiData->coder );
+  if ( result < 0 ) {
+    data->doInput = false;
+    std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing MIDI event parser!\n\n";
+    return 0;
+  }
+  unsigned char *buffer = (unsigned char *) malloc(apiData->bufferSize);
+  if ( buffer == NULL ) {
+    data->doInput = false;
+    std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing buffer memory!\n\n";
+    return 0;
+  }
+  snd_midi_event_init( apiData->coder );
+
+  while ( data->doInput ) {
+
+    if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) {
+      // No data pending ... sleep a bit.
+      usleep( 1000 );
+      continue;
+    }
+
+    // If here, there should be data.
+    result = snd_seq_event_input( apiData->seq, &ev );
+    if ( result == -ENOSPC ) {
+      std::cerr << "\nRtMidiIn::alsaMidiHandler: MIDI input buffer overrun!\n\n";
+      continue;
+    }
+    else if ( result <= 0 ) {
+      std::cerr << "RtMidiIn::alsaMidiHandler: unknown MIDI input error!\n";
+      continue;
+    }
+
+    // This is a bit weird, but we now have to decode an ALSA MIDI
+    // event (back) into MIDI bytes.  We'll ignore non-MIDI types.
+    message.bytes.clear();
+    switch (ev->type) {
+
+		case SND_SEQ_EVENT_PORT_SUBSCRIBED:
+#if defined(__RTMIDI_DEBUG__)
+      std::cout << "RtMidiIn::alsaMidiHandler: port connection made!\n";
+#endif
+      break;
+
+		case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
+      std::cerr << "RtMidiIn::alsaMidiHandler: port connection has closed!\n";
+      data->doInput = false;
+      break;
+
+    case SND_SEQ_EVENT_QFRAME: // MIDI time code
+      if ( data->ignoreFlags & 0x02 ) break;
+
+    case SND_SEQ_EVENT_SENSING: // Active sensing
+      if ( data->ignoreFlags & 0x04 ) break;
+
+		case SND_SEQ_EVENT_SYSEX:
+      if ( (data->ignoreFlags & 0x01) ) break;
+      if ( ev->data.ext.len > apiData->bufferSize ) {
+        apiData->bufferSize = ev->data.ext.len;
+        free(buffer);
+        buffer = (unsigned char *) malloc(apiData->bufferSize);
+        if ( buffer == NULL ) {
+          data->doInput = false;
+          std::cerr << "\nRtMidiIn::alsaMidiHandler: error resizing buffer memory!\n\n";
+          break;
+        }
+      }
+
+    default:
+      nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev );
+      if ( nBytes <= 0 ) {
+#if defined(__RTMIDI_DEBUG__)
+        std::cerr << "\nRtMidiIn::alsaMidiHandler: event parsing error or not a MIDI event!\n\n";
+#endif
+        break;
+      }
+      message.bytes.assign( buffer, &buffer[nBytes] );
+
+      // Save last status byte in case of running status.
+      if ( message.bytes[0] & 0x80 ) lastStatus = message.bytes[0];
+      else if ( lastStatus ) message.bytes.insert( message.bytes.begin(), lastStatus );
+      // I found the ALSA sequencer documentation to be very inadequate,
+      // especially regarding timestamps.  So, I ignore the event
+      // timestamp and use system time to determine ours.
+      message.timeStamp = 0.0;
+      (void)gettimeofday(&tv, (struct timezone *)NULL);
+      time = (tv.tv_sec * 1000000) + tv.tv_usec;
+      lastTime = time;
+      time -= apiData->lastTime;
+      apiData->lastTime = lastTime;
+      if ( data->firstMessage == true )
+        data->firstMessage = false;
+      else {
+        message.timeStamp = time * 0.000001;
+      }
+    }
+
+    snd_seq_free_event(ev);
+    if ( message.bytes.size() == 0 ) continue;
+
+    if ( data->usingCallback ) {
+      RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+      callback( message.timeStamp, &message.bytes, data->userData );
+    }
+    else {
+      // As long as we haven't reached our queue size limit, push the message.
+      if ( data->queueLimit > data->queue.size() )
+        data->queue.push( message );
+      else
+        std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+    }
+  }
+
+  snd_midi_event_free( apiData->coder );
+  apiData->coder = 0;
+  return 0;
+}
+
+void RtMidiIn :: initialize( void )
+{
+  // Set up the ALSA sequencer client.
+	snd_seq_t *seq;
+  int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT, 0);
+  if ( result < 0 ) {
+    errorString_ = "RtMidiIn::initialize: error creating ALSA sequencer input client object.";
+    error( RtError::DRIVER_ERROR );
+	}
+
+  // Set client name.
+  snd_seq_set_client_name(seq, "RtMidi Input Client");
+
+  // Save our api-specific connection information.
+  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;
+  data->seq = seq;
+  data->vport = -1;
+  apiData_ = (void *) data;
+  inputData_.apiData = (void *) data;
+}
+
+// This function is used to count or get the pinfo structure for a given port number.
+unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber )
+{
+	snd_seq_client_info_t *cinfo;
+  int client;
+  int count = 0;
+	snd_seq_client_info_alloca( &cinfo );
+
+	snd_seq_client_info_set_client( cinfo, -1 );
+	while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) {
+    client = snd_seq_client_info_get_client( cinfo );
+    if ( client == 0 ) continue;
+		// Reset query info
+		snd_seq_port_info_set_client( pinfo, client );
+		snd_seq_port_info_set_port( pinfo, -1 );
+		while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) {
+      if ( !PORT_TYPE( pinfo, type ) )  continue;
+      if ( count == portNumber ) return 1;
+      count++;
+		}
+	}
+
+  // If a negative portNumber was used, return the port count.
+  if ( portNumber < 0 ) return count;
+  return 0;
+}
+
+void RtMidiIn :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nSrc = this->getPortCount();
+  if (nSrc < 1) {
+    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+  std::ostringstream ost;
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) {
+    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+
+  snd_seq_addr_t sender, receiver;
+  sender.client = snd_seq_port_info_get_client( pinfo );
+  sender.port = snd_seq_port_info_get_port( pinfo );
+  receiver.client = snd_seq_client_id( data->seq );
+  if ( data->vport < 0 ) {
+    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Input",
+                                              SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
+                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+    if ( data->vport < 0 ) {
+      errorString_ = "RtMidiIn::openPort: ALSA error creating input port.";
+      error( RtError::DRIVER_ERROR );
+    }
+  }
+
+  receiver.port = data->vport;
+
+  // Make subscription
+  snd_seq_port_subscribe_malloc( &data->subscription );
+  snd_seq_port_subscribe_set_sender(data->subscription, &sender);
+  snd_seq_port_subscribe_set_dest(data->subscription, &receiver);
+  snd_seq_port_subscribe_set_time_update(data->subscription, 1);
+  snd_seq_port_subscribe_set_time_real(data->subscription, 1);
+  if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {
+    errorString_ = "RtMidiIn::openPort: ALSA error making port connection.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  if ( inputData_.doInput == false ) {
+    // Start our MIDI input thread.
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setschedpolicy(&attr, SCHED_RR);
+
+    inputData_.doInput = true;
+    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
+    pthread_attr_destroy(&attr);
+    if (err) {
+      snd_seq_unsubscribe_port( data->seq, data->subscription );
+      snd_seq_port_subscribe_free( data->subscription );
+      inputData_.doInput = false;
+      errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!";
+      error( RtError::THREAD_ERROR );
+    }
+  }
+
+  connected_ = true;
+}
+
+void RtMidiIn :: openVirtualPort()
+{
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( data->vport < 0 ) {
+    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Input",
+                                              SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
+                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+
+    if ( data->vport < 0 ) {
+      errorString_ = "RtMidiIn::openVirtualPort: ALSA error creating virtual port.";
+      error( RtError::DRIVER_ERROR );
+    }
+  }
+
+  if ( inputData_.doInput == false ) {
+    // Start our MIDI input thread.
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    pthread_attr_setschedpolicy(&attr, SCHED_RR);
+
+    inputData_.doInput = true;
+    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
+    pthread_attr_destroy(&attr);
+    if (err) {
+      snd_seq_unsubscribe_port( data->seq, data->subscription );
+      snd_seq_port_subscribe_free( data->subscription );
+      inputData_.doInput = false;
+      errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!";
+      error( RtError::THREAD_ERROR );
+    }
+  }
+}
+
+void RtMidiIn :: closePort( void )
+{
+  if ( connected_ ) {
+    AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+    snd_seq_unsubscribe_port( data->seq, data->subscription );
+    snd_seq_port_subscribe_free( data->subscription );
+    connected_ = false;
+  }
+}
+
+RtMidiIn :: ~RtMidiIn()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Shutdown the input thread.
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( inputData_.doInput ) {
+    inputData_.doInput = false;
+    pthread_join( data->thread, NULL );
+  }
+
+  // Cleanup.
+  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );
+  snd_seq_close( data->seq );
+  delete data;
+}
+
+unsigned int RtMidiIn :: getPortCount()
+{
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 );
+}
+
+std::string RtMidiIn :: getPortName( unsigned int portNumber )
+{
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) {
+    std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) );
+    return stringName;
+  }
+
+  // If we get here, we didn't find a match.
+  errorString_ = "RtMidiIn::getPortName: error looking for port name!";
+  error( RtError::INVALID_PARAMETER );
+  return 0;
+}
+
+//*********************************************************************//
+//  API: LINUX ALSA
+//  Class Definitions: RtMidiOut
+//*********************************************************************//
+
+unsigned int RtMidiOut :: getPortCount()
+{
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 );
+}
+
+std::string RtMidiOut :: getPortName( unsigned int portNumber )
+{
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) {
+    std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) );
+    return stringName;
+  }
+
+  // If we get here, we didn't find a match.
+  errorString_ = "RtMidiOut::getPortName: error looking for port name!";
+  error( RtError::INVALID_PARAMETER );
+  return 0;
+}
+
+void RtMidiOut :: initialize( void )
+{
+  // Set up the ALSA sequencer client.
+	snd_seq_t *seq;
+  int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0);
+  if ( result < 0 ) {
+    errorString_ = "RtMidiOut::initialize: error creating ALSA sequencer client object.";
+    error( RtError::DRIVER_ERROR );
+	}
+
+  // Set client name.
+  snd_seq_set_client_name(seq, "RtMidi Output Client");
+
+  // Save our api-specific connection information.
+  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;
+  data->seq = seq;
+  data->vport = -1;
+  data->bufferSize = 32;
+  data->coder = 0;
+  data->buffer = 0;
+  result = snd_midi_event_new( data->bufferSize, &data->coder );
+  if ( result < 0 ) {
+    delete data;
+    errorString_ = "RtMidiOut::initialize: error initializing MIDI event parser!\n\n";
+    error( RtError::DRIVER_ERROR );
+  }
+  data->buffer = (unsigned char *) malloc( data->bufferSize );
+  if ( data->buffer == NULL ) {
+    delete data;
+    errorString_ = "RtMidiOut::initialize: error allocating buffer memory!\n\n";
+    error( RtError::MEMORY_ERROR );
+  }
+  snd_midi_event_init( data->coder );
+  apiData_ = (void *) data;
+}
+
+void RtMidiOut :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiOut::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nSrc = this->getPortCount();
+  if (nSrc < 1) {
+    errorString_ = "RtMidiOut::openPort: no MIDI output sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+	snd_seq_port_info_t *pinfo;
+	snd_seq_port_info_alloca( &pinfo );
+  std::ostringstream ost;
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) {
+    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  snd_seq_addr_t sender, receiver;
+  receiver.client = snd_seq_port_info_get_client( pinfo );
+  receiver.port = snd_seq_port_info_get_port( pinfo );
+  sender.client = snd_seq_client_id( data->seq );
+
+  if ( data->vport < 0 ) {
+    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output",
+                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
+                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+    if ( data->vport < 0 ) {
+      errorString_ = "RtMidiOut::openPort: ALSA error creating output port.";
+      error( RtError::DRIVER_ERROR );
+    }
+  }
+
+  sender.port = data->vport;
+
+  // Make subscription
+  snd_seq_port_subscribe_malloc( &data->subscription );
+  snd_seq_port_subscribe_set_sender(data->subscription, &sender);
+  snd_seq_port_subscribe_set_dest(data->subscription, &receiver);
+  snd_seq_port_subscribe_set_time_update(data->subscription, 1);
+  snd_seq_port_subscribe_set_time_real(data->subscription, 1);
+  if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {
+    errorString_ = "RtMidiOut::openPort: ALSA error making port connection.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  connected_ = true;
+}
+
+void RtMidiOut :: closePort( void )
+{
+  if ( connected_ ) {
+    AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+    snd_seq_unsubscribe_port( data->seq, data->subscription );
+    snd_seq_port_subscribe_free( data->subscription );
+    connected_ = false;
+  }
+}
+
+void RtMidiOut :: openVirtualPort()
+{
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( data->vport < 0 ) {
+    data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output",
+                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
+                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+
+    if ( data->vport < 0 ) {
+      errorString_ = "RtMidiOut::openVirtualPort: ALSA error creating virtual port.";
+      error( RtError::DRIVER_ERROR );
+    }
+  }
+}
+
+RtMidiOut :: ~RtMidiOut()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );
+  if ( data->coder ) snd_midi_event_free( data->coder );
+  if ( data->buffer ) free( data->buffer );
+  snd_seq_close( data->seq );
+  delete data;
+}
+
+void RtMidiOut :: sendMessage( std::vector<unsigned char> *message )
+{
+  int result;
+  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
+  unsigned int nBytes = message->size();
+  if ( nBytes > data->bufferSize ) {
+    data->bufferSize = nBytes;
+    result = snd_midi_event_resize_buffer ( data->coder, nBytes);
+    if ( result != 0 ) {
+      errorString_ = "RtMidiOut::sendMessage: ALSA error resizing MIDI event buffer.";
+      error( RtError::DRIVER_ERROR );
+    }
+    free (data->buffer);
+    data->buffer = (unsigned char *) malloc( data->bufferSize );
+    if ( data->buffer == NULL ) {
+    errorString_ = "RtMidiOut::initialize: error allocating buffer memory!\n\n";
+    error( RtError::MEMORY_ERROR );
+    }
+  }
+
+  snd_seq_event_t ev;
+  snd_seq_ev_clear(&ev);
+  snd_seq_ev_set_source(&ev, data->vport);
+  snd_seq_ev_set_subs(&ev);
+  snd_seq_ev_set_direct(&ev);
+  for ( unsigned int i=0; i<nBytes; i++ ) data->buffer[i] = message->at(i);
+  result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev );
+  if ( result < (int)nBytes ) {
+    errorString_ = "RtMidiOut::sendMessage: event parsing error!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  // Send the event.
+  result = snd_seq_event_output(data->seq, &ev);
+  if ( result < 0 ) {
+    errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port.";
+    error( RtError::WARNING );
+  }
+  snd_seq_drain_output(data->seq);
+}
+
+#endif // __LINUX_ALSA__
+
+
+//*********************************************************************//
+//  API: IRIX MD
+//*********************************************************************//
+
+// API information gleamed from:
+//   http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?cmd=getdoc&coll=0650&db=man&fname=3%20mdIntro
+
+// If the Makefile doesn't work, try the following:
+// CC -o midiinfo -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp midiinfo.cpp -lpthread -lmd
+// CC -o midiout -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp midiout.cpp -lpthread -lmd
+// CC -o qmidiin -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp qmidiin.cpp -lpthread -lmd
+// CC -o cmidiin -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp cmidiin.cpp -lpthread -lmd
+
+#if defined(__IRIX_MD__)
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+// Irix MIDI header file.
+#include <dmedia/midi.h>
+
+// A structure to hold variables related to the IRIX API
+// implementation.
+struct IrixMidiData {
+  MDport port;
+  pthread_t thread;
+};
+
+//*********************************************************************//
+//  API: IRIX
+//  Class Definitions: RtMidiIn
+//*********************************************************************//
+
+extern "C" void *irixMidiHandler( void *ptr )
+{
+  RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (ptr);
+  IrixMidiData *apiData = static_cast<IrixMidiData *> (data->apiData);
+
+  bool continueSysex = false;
+  unsigned char status;
+  unsigned short size;
+  MDevent event;
+  int fd = mdGetFd( apiData->port );
+  if ( fd < 0 ) {
+    data->doInput = false;
+    std::cerr << "\nRtMidiIn::irixMidiHandler: error getting port descriptor!\n\n";
+    return 0;
+  }
+
+  fd_set mask, rmask;
+  FD_ZERO( &mask );
+  FD_SET( fd, &mask );
+  struct timeval timeout = {0, 0};
+  RtMidiIn::MidiMessage message;
+  int result;
+
+  while ( data->doInput ) {
+
+    rmask = mask;
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+    if ( select( fd+1, &rmask, NULL, NULL, &timeout ) <= 0 ) {
+      // No data pending ... sleep a bit.
+      usleep( 1000 );
+      continue;
+    }
+
+    // If here, there should be data.
+    result = mdReceive( apiData->port, &event, 1);
+    if ( result <= 0 ) {
+      std::cerr << "\nRtMidiIn::irixMidiHandler: MIDI input read error!\n\n";
+      continue;
+    }
+
+    message.timeStamp = event.stamp * 0.000000001;
+
+    size = 0;
+    status = event.msg[0];
+    if ( !(status & 0x80) ) continue;
+    if ( status == 0xF0 ) {
+      // Sysex message ... can be segmented across multiple messages.
+      if ( !(data->ignoreFlags & 0x01) ) {
+        if ( continueSysex ) {
+          // We have a continuing, segmented sysex message.  Append
+          // the new bytes to our existing message.
+          for ( int i=0; i<event.msglen; i++ )
+            message.bytes.push_back( event.sysexmsg[i] );
+          if ( event.sysexmsg[event.msglen-1] == 0xF7 ) continueSysex = false;
+          if ( !continueSysex ) {
+            // If not a continuing sysex message, invoke the user callback function or queue the message.
+            if ( data->usingCallback && message.bytes.size() > 0 ) {
+              RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+              callback( message.timeStamp, &message.bytes, data->userData );
+            }
+            else {
+              // As long as we haven't reached our queue size limit, push the message.
+              if ( data->queueLimit > data->queue.size() )
+                data->queue.push( message );
+              else
+                std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+            }
+            message.bytes.clear();
+          }
+        }
+      }
+      mdFree( NULL );
+      continue;
+    }
+    else if ( status < 0xC0 ) size = 3;
+    else if ( status < 0xE0 ) size = 2;
+    else if ( status < 0xF0 ) size = 3;
+    else if ( status < 0xF3 ) {
+      if ( status == 0xF1 && !(data->ignoreFlags & 0x02) ) {
+        // A MIDI time code message and we're not ignoring it.
+        size = 3;
+      }
+    }
+    else if ( status == 0xF3 ) size = 2;
+    else if ( status == 0xFE ) { // MIDI active sensing
+      if ( !(data->ignoreFlags & 0x04) )
+        size = 1;
+    }
+    else size = 1;
+
+    // Copy the MIDI data to our vector.
+    if ( size ) {
+      message.bytes.assign( &event.msg[0], &event.msg[size] );
+      // Invoke the user callback function or queue the message.
+      if ( data->usingCallback ) {
+        RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+        callback( message.timeStamp, &message.bytes, data->userData );
+      }
+      else {
+        // As long as we haven't reached our queue size limit, push the message.
+        if ( data->queueLimit > data->queue.size() )
+          data->queue.push( message );
+        else
+          std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+      }
+      message.bytes.clear();
+    }
+  }
+
+  return 0;
+}
+
+void RtMidiIn :: initialize( void )
+{
+  // Initialize the Irix MIDI system.  At the moment, we will not
+  // worry about a return value of zero (ports) because there is a
+  // chance the user could plug something in after instantiation.
+  int nPorts = mdInit();
+
+  // Create our api-specific connection information.
+  IrixMidiData *data = (IrixMidiData *) new IrixMidiData;
+  apiData_ = (void *) data;
+  inputData_.apiData = (void *) data;
+}
+
+void RtMidiIn :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  int nPorts = mdInit();
+  if (nPorts < 1) {
+    errorString_ = "RtMidiIn::openPort: no Irix MIDI input sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nPorts ) {
+    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+  data->port = mdOpenInPort( mdGetName(portNumber) );
+  if ( data->port == NULL ) {
+    ost << "RtMidiIn::openPort: Irix error opening the port (" << portNumber << ").";
+    errorString_ = ost.str();
+    error( RtError::DRIVER_ERROR );
+  }
+  mdSetStampMode(data->port, MD_DELTASTAMP);
+
+  // Start our MIDI input thread.
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+  pthread_attr_setschedpolicy(&attr, SCHED_RR);
+
+  inputData_.doInput = true;
+  int err = pthread_create(&data->thread, &attr, irixMidiHandler, &inputData_);
+  pthread_attr_destroy(&attr);
+  if (err) {
+    mdClosePort( data->port );
+    inputData_.doInput = false;
+    errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!";
+    error( RtError::THREAD_ERROR );
+  }
+
+  connected_ = true;
+}
+
+void RtMidiIn :: openVirtualPort()
+{
+  // This function cannot be implemented for the Irix MIDI API.
+}
+
+void RtMidiIn :: closePort( void )
+{
+  if ( connected_ ) {
+    IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+    mdClosePort( data->port );
+    connected_ = false;
+
+    // Shutdown the input thread.
+    inputData_.doInput = false;
+    pthread_join( data->thread, NULL );
+  }
+}
+
+RtMidiIn :: ~RtMidiIn()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+  delete data;
+}
+
+unsigned int RtMidiIn :: getPortCount()
+{
+  int nPorts = mdInit();
+  if ( nPorts >= 0 ) return nPorts;
+  else return 0;
+}
+
+std::string RtMidiIn :: getPortName( unsigned int portNumber )
+{
+  int nPorts = mdInit();
+
+  std::ostringstream ost;
+  if ( portNumber >= nPorts ) {
+    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  std::string stringName = std::string( mdGetName( portNumber ) );
+  return stringName;
+}
+
+//*********************************************************************//
+//  API: IRIX MD
+//  Class Definitions: RtMidiOut
+//*********************************************************************//
+
+unsigned int RtMidiOut :: getPortCount()
+{
+  int nPorts = mdInit();
+  if ( nPorts >= 0 ) return nPorts;
+  else return 0;
+}
+
+std::string RtMidiOut :: getPortName( unsigned int portNumber )
+{
+  int nPorts = mdInit();
+
+  std::ostringstream ost;
+  if ( portNumber >= nPorts ) {
+    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  std::string stringName = std::string( mdGetName( portNumber ) );
+  return stringName;
+}
+
+void RtMidiOut :: initialize( void )
+{
+  // Initialize the Irix MIDI system.  At the moment, we will not
+  // worry about a return value of zero (ports) because there is a
+  // chance the user could plug something in after instantiation.
+  int nPorts = mdInit();
+
+  // Create our api-specific connection information.
+  IrixMidiData *data = (IrixMidiData *) new IrixMidiData;
+  apiData_ = (void *) data;
+}
+
+void RtMidiOut :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiOut::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  int nPorts = mdInit();
+  if (nPorts < 1) {
+    errorString_ = "RtMidiOut::openPort: no Irix MIDI output sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nPorts ) {
+    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+  data->port = mdOpenOutPort( mdGetName(portNumber) );
+  if ( data->port == NULL ) {
+    ost << "RtMidiOut::openPort: Irix error opening the port (" << portNumber << ").";
+    errorString_ = ost.str();
+    error( RtError::DRIVER_ERROR );
+  }
+  mdSetStampMode(data->port, MD_NOSTAMP);
+
+  connected_ = true;
+}
+
+void RtMidiOut :: closePort( void )
+{
+  if ( connected_ ) {
+    IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+    mdClosePort( data->port );
+    connected_ = false;
+  }
+}
+
+void RtMidiOut :: openVirtualPort()
+{
+  // This function cannot be implemented for the Irix MIDI API.
+}
+
+RtMidiOut :: ~RtMidiOut()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+  delete data;
+}
+
+void RtMidiOut :: sendMessage( std::vector<unsigned char> *message )
+{
+  int result;
+  MDevent event;
+  IrixMidiData *data = static_cast<IrixMidiData *> (apiData_);
+  char *buffer = 0;
+
+  unsigned int nBytes = message->size();
+  if ( nBytes == 0 ) return;
+  event.stamp = 0;
+  if ( message->at(0) == 0xF0 ) {
+    if ( nBytes < 3 ) return; // check for bogus sysex
+    event.msg[0] = 0xF0;
+    event.msglen = nBytes;
+    buffer = (char *) malloc( nBytes );
+    for ( int i=0; i<nBytes; i++ ) buffer[i] = message->at(i);
+    event.sysexmsg = buffer;
+  }
+  else {
+    for ( int i=0; i<nBytes; i++ )
+      event.msg[i] = message->at(i);
+  }
+
+  // Send the event.
+  result = mdSend( data->port, &event, 1 );
+  if ( buffer ) free( buffer );
+  if ( result < 1 ) {
+    errorString_ = "RtMidiOut::sendMessage: IRIX error sending MIDI message!";
+    error( RtError::WARNING );
+    return;
+  }
+}
+
+#endif // __IRIX_MD__
+
+//*********************************************************************//
+//  API: Windows Multimedia Library (MM)
+//*********************************************************************//
+
+// API information deciphered from:
+//  - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp
+
+#if defined(__WINDOWS_MM__)
+
+// The Windows MM API is based on the use of a callback function for
+// MIDI input.  We convert the system specific time stamps to delta
+// time values.
+
+// Windows MM MIDI header files.
+#include <windows.h>
+#include <mmsystem.h>
+
+// A structure to hold variables related to the CoreMIDI API
+// implementation.
+struct WinMidiData {
+  HMIDIIN inHandle;    // Handle to Midi Input Device
+  HMIDIOUT outHandle;  // Handle to Midi Output Device
+  DWORD lastTime;
+  RtMidiIn::MidiMessage message;
+};
+
+//*********************************************************************//
+//  API: Windows MM
+//  Class Definitions: RtMidiIn
+//*********************************************************************//
+
+static void CALLBACK midiInputCallback( HMIDIOUT hmin,
+                                        UINT inputStatus, 
+                                        DWORD instancePtr,
+                                        DWORD midiMessage,
+                                        DWORD timestamp )
+{
+  if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA ) return;
+
+  //RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (instancePtr);
+  RtMidiIn::RtMidiInData *data = (RtMidiIn::RtMidiInData *)instancePtr;
+  WinMidiData *apiData = static_cast<WinMidiData *> (data->apiData);
+
+  // Calculate time stamp.
+  apiData->message.timeStamp = 0.0;
+  if ( data->firstMessage == true ) data->firstMessage = false;
+  else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;
+  apiData->lastTime = timestamp;
+
+  if ( inputStatus == MIM_DATA ) { // Channel or system message
+
+    // Make sure the first byte is a status byte.
+    unsigned char status = (unsigned char) (midiMessage & 0x000000FF);
+    if ( !(status & 0x80) ) return;
+
+    // Determine the number of bytes in the MIDI message.
+    unsigned short nBytes = 1;
+    if ( status < 0xC0 ) nBytes = 3;
+    else if ( status < 0xE0 ) nBytes = 2;
+    else if ( status < 0xF0 ) nBytes = 3;
+    else if ( status < 0xF3 ) {
+      // A MIDI time code message and we're ignoring it.
+      if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) return;
+      nBytes = 3;
+    }
+    else if ( status == 0xF3 ) nBytes = 2;
+    else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
+      // A MIDI active sensing message and we're ignoring it.
+      return;
+    }
+
+    // Copy bytes to our MIDI message.
+    unsigned char *ptr = (unsigned char *) &midiMessage;
+    for ( int i=0; i<nBytes; i++ ) apiData->message.bytes.push_back( *ptr++ );
+  }
+  else { // Sysex message
+    MIDIHDR *sysex = ( MIDIHDR *) midiMessage;
+    for ( int i=0; i<(int)sysex->dwBytesRecorded; i++ )
+      apiData->message.bytes.push_back( sysex->lpData[i] );
+    if ( apiData->message.bytes.back() != 0xF7 ) return;
+  }
+
+  if ( data->usingCallback ) {
+    RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
+    callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );
+  }
+  else {
+    // As long as we haven't reached our queue size limit, push the message.
+    if ( data->queueLimit > data->queue.size() )
+      data->queue.push( apiData->message );
+    else
+      std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
+  }
+
+  // Clear the vector for the next input message.  Note that doing
+  // this here allows our code to work for sysex messages which are
+  // segmented across multiple buffers.
+  apiData->message.bytes.clear();
+}
+
+void RtMidiIn :: initialize( void )
+{
+  // We'll issue a warning here if no devices are available but not
+  // throw an error since the user can plugin something later.
+  unsigned int nDevices = midiInGetNumDevs();
+  if ( nDevices == 0 ) {
+    errorString_ = "RtMidiIn::initialize: no MIDI input devices currently available.";
+    error( RtError::WARNING );
+  }
+
+  // Save our api-specific connection information.
+  WinMidiData *data = (WinMidiData *) new WinMidiData;
+  apiData_ = (void *) data;
+  inputData_.apiData = (void *) data;
+  data->message.bytes.clear();  // needs to be empty for first input message
+}
+
+void RtMidiIn :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiIn::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nDevices = midiInGetNumDevs();
+  if (nDevices == 0) {
+    errorString_ = "RtMidiIn::openPort: no MIDI input sources found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nDevices ) {
+    ost << "RtMidiIn::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+  MMRESULT result = midiInOpen( &data->inHandle,
+                                portNumber,
+                                (DWORD)&midiInputCallback,
+                                (DWORD)&inputData_,
+                                CALLBACK_FUNCTION );
+  if ( result != MMSYSERR_NOERROR ) {
+    errorString_ = "RtMidiIn::openPort: error creating Windows MM MIDI input port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  result = midiInStart( data->inHandle );
+  if ( result != MMSYSERR_NOERROR ) {
+    midiInClose( data->inHandle );
+    errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  connected_ = true;
+}
+
+void RtMidiIn :: openVirtualPort()
+{
+  // This function cannot be implemented for the Windows MM MIDI API.
+}
+
+void RtMidiIn :: closePort( void )
+{
+  if ( connected_ ) {
+    WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+    midiInReset( data->inHandle );
+    midiInStop( data->inHandle );
+    midiInClose( data->inHandle );
+    connected_ = false;
+  }
+}
+
+RtMidiIn :: ~RtMidiIn()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+  delete data;
+}
+
+unsigned int RtMidiIn :: getPortCount()
+{
+  return midiInGetNumDevs();
+}
+
+std::string RtMidiIn :: getPortName( unsigned int portNumber )
+{
+  unsigned int nDevices = midiInGetNumDevs();
+  if ( portNumber >= nDevices ) {
+    std::ostringstream ost;
+    ost << "RtMidiIn::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  MIDIINCAPS deviceCaps;
+  MMRESULT result = midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS));
+
+  std::string stringName = std::string( deviceCaps.szPname );
+  return stringName;
+}
+
+//*********************************************************************//
+//  API: Windows MM
+//  Class Definitions: RtMidiOut
+//*********************************************************************//
+
+unsigned int RtMidiOut :: getPortCount()
+{
+  return midiOutGetNumDevs();
+}
+
+std::string RtMidiOut :: getPortName( unsigned int portNumber )
+{
+  unsigned int nDevices = midiOutGetNumDevs();
+  if ( portNumber >= nDevices ) {
+    std::ostringstream ost;
+    ost << "RtMidiOut::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  MIDIOUTCAPS deviceCaps;
+  MMRESULT result = midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));
+
+  std::string stringName = std::string( deviceCaps.szPname );
+  return stringName;
+}
+
+void RtMidiOut :: initialize( void )
+{
+  // We'll issue a warning here if no devices are available but not
+  // throw an error since the user can plug something in later.
+  unsigned int nDevices = midiOutGetNumDevs();
+  if ( nDevices == 0 ) {
+    errorString_ = "RtMidiOut::initialize: no MIDI output devices currently available.";
+    error( RtError::WARNING );
+  }
+
+  // Save our api-specific connection information.
+  WinMidiData *data = (WinMidiData *) new WinMidiData;
+  apiData_ = (void *) data;
+}
+
+void RtMidiOut :: openPort( unsigned int portNumber )
+{
+  if ( connected_ ) {
+    errorString_ = "RtMidiOut::openPort: a valid connection already exists!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  unsigned int nDevices = midiOutGetNumDevs();
+  if (nDevices < 1) {
+    errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!";
+    error( RtError::NO_DEVICES_FOUND );
+  }
+
+  std::ostringstream ost;
+  if ( portNumber >= nDevices ) {
+    ost << "RtMidiOut::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
+    errorString_ = ost.str();
+    error( RtError::INVALID_PARAMETER );
+  }
+
+  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+  MMRESULT result = midiOutOpen( &data->outHandle,
+                                 portNumber,
+                                 (DWORD)NULL,
+                                 (DWORD)NULL,
+                                 CALLBACK_NULL );
+  if ( result != MMSYSERR_NOERROR ) {
+    errorString_ = "RtMidiOut::openPort: error creating Windows MM MIDI output port.";
+    error( RtError::DRIVER_ERROR );
+  }
+
+  connected_ = true;
+}
+
+void RtMidiOut :: closePort( void )
+{
+  if ( connected_ ) {
+    WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+    midiOutReset( data->outHandle );
+    midiOutClose( data->outHandle );
+    connected_ = false;
+  }
+}
+
+void RtMidiOut :: openVirtualPort()
+{
+  // This function cannot be implemented for the Windows MM MIDI API.
+}
+
+RtMidiOut :: ~RtMidiOut()
+{
+  // Close a connection if it exists.
+  closePort();
+
+  // Cleanup.
+  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+  delete data;
+}
+
+void RtMidiOut :: sendMessage( std::vector<unsigned char> *message )
+{
+  unsigned int nBytes = message->size();
+  if ( nBytes == 0 ) {
+    errorString_ = "RtMidiOut::sendMessage: message argument is empty!";
+    error( RtError::WARNING );
+    return;
+  }
+
+  MMRESULT result;
+  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
+  if ( message->at(0) == 0xF0 ) { // Sysex message
+
+    // Allocate buffer for sysex data.
+    char *buffer = (char *) malloc( nBytes );
+    if ( buffer == NULL ) {
+      errorString_ = "RtMidiOut::sendMessage: error allocating sysex message memory!";
+      error( RtError::MEMORY_ERROR );
+    }
+
+    // Copy data to buffer.
+    for ( unsigned int i=0; i<nBytes; i++ ) buffer[i] = message->at(i);
+
+    // Create and prepare MIDIHDR structure.
+    MIDIHDR sysex;
+    sysex.lpData = (LPSTR) buffer;
+    sysex.dwBufferLength = nBytes;
+    sysex.dwFlags = 0;
+    result = midiOutPrepareHeader( data->outHandle,  &sysex, sizeof(MIDIHDR) ); 
+    if ( result != MMSYSERR_NOERROR ) {
+      free( buffer );
+      errorString_ = "RtMidiOut::sendMessage: error preparing sysex header.";
+      error( RtError::DRIVER_ERROR );
+    }
+
+    // Send the message.
+    result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) );
+    if ( result != MMSYSERR_NOERROR ) {
+      free( buffer );
+      errorString_ = "RtMidiOut::sendMessage: error sending sysex message.";
+      error( RtError::DRIVER_ERROR );
+    }
+
+    // Unprepare the buffer and MIDIHDR.
+    while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 );
+    free( buffer );
+
+  }
+  else { // Channel or system message.
+
+    // Make sure the message size isn't too big.
+    if ( nBytes > 3 ) {
+      errorString_ = "RtMidiOut::sendMessage: message size is greater than 3 bytes (and not sysex)!";
+      error( RtError::WARNING );
+      return;
+    }
+
+    // Pack MIDI bytes into double word.
+    DWORD packet;
+    unsigned char *ptr = (unsigned char *) &packet;
+    for ( unsigned int i=0; i<nBytes; i++ ) {
+      *ptr = message->at(i);
+      ptr++;
+    }
+
+    // Send the message immediately.
+    result = midiOutShortMsg( data->outHandle, packet );
+    if ( result != MMSYSERR_NOERROR ) {
+      errorString_ = "RtMidiOut::sendMessage: error sending MIDI message.";
+      error( RtError::DRIVER_ERROR );
+    }
+  }
+}
+
+#endif  // __WINDOWS_MM__

+ 282 - 0
RtMidi.h

@@ -0,0 +1,282 @@
+/**********************************************************************/
+/*! \class RtMidi
+    \brief An abstract base class for realtime MIDI input/output.
+
+    This class implements some common functionality for the realtime
+    MIDI input/output subclasses RtMidiIn and RtMidiOut.
+
+    RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
+
+    RtMidi: realtime MIDI i/o C++ classes
+    Copyright (c) 2003-2004 Gary P. Scavone
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation files
+    (the "Software"), to deal in the Software without restriction,
+    including without limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of the Software,
+    and to permit persons to whom the Software is furnished to do so,
+    subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    Any person wishing to distribute modifications to the Software is
+    requested to send the modifications to the original developer so that
+    they can be incorporated into the canonical version.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+/**********************************************************************/
+
+// RtMidi: Version 1.0.0, 17 September 2004
+
+#ifndef RTMIDI_H
+#define RTMIDI_H
+
+#include "RtError.h"
+#include <string>
+
+class RtMidi
+{
+ protected:
+
+  RtMidi();
+
+  virtual ~RtMidi() {};
+
+  // A basic error reporting function for internal use in the RtMidi
+  // subclasses.  The behavior of this function can be modified to
+  // suit specific needs.
+  void error( RtError::Type type );
+
+  virtual void openPort( unsigned int portNumber = 0 ) = 0;
+
+  void *apiData_;
+  bool connected_;
+  std::string errorString_;
+};
+
+/**********************************************************************/
+/*! \class RtMidiIn
+    \brief A realtime MIDI input class.
+
+    This class provides a common, platform-independent API for
+    realtime MIDI input.  It allows access to a single MIDI input
+    port.  Incoming MIDI messages are either saved to a queue for
+    retrieval using the getMessage() function or immediately passed to
+    a user-specified callback function.  Create multiple instances of
+    this class to connect to more than one MIDI device at the same
+    time.  With the OS-X and Linux ALSA MIDI APIs, it is also possible
+    to open a virtual input port to which other MIDI software clients
+    can connect.
+
+    by Gary P. Scavone, 2003-2004.
+*/
+/**********************************************************************/
+
+#include <vector>
+#include <queue>
+
+class RtMidiIn : public RtMidi
+{
+ public:
+
+  //! User callback function type definition.
+  typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData);
+
+  //! Default constructor.
+  /*!
+      An exception will be thrown if a MIDI system initialization error occurs.
+  */
+  RtMidiIn();
+
+  //! If a MIDI connection is still open, it will be closed by the destructor.
+  ~RtMidiIn();
+
+  //! Open a MIDI input connection.
+  /*!
+      An optional port number greater than 0 can be specified.
+      Otherwise, the default or first port found is opened.
+  */
+  void openPort( unsigned int portNumber = 0 );
+
+  //! Create a virtual input port to allow software connections (OS X and ALSA only).
+  /*!
+      This function creates a virtual MIDI input port to which other
+      software applications can connect.  This type of functionality
+      is currently only supported by the Macintosh OS-X and Linux ALSA
+      APIs (the function does nothing for the other APIs).
+  */
+  void openVirtualPort();
+
+  //! Set a callback function to be invoked for incoming MIDI messages.
+  /*!
+      The callback function will be called whenever an incoming MIDI
+      message is received.  While not absolutely necessary, it is best
+      to set the callback function before opening a MIDI port to avoid
+      leaving some messages in the queue.
+  */
+  void setCallback( RtMidiCallback callback, void *userData = 0 );
+
+  //! Cancel use of the current callback function (if one exists).
+  /*!
+      Subsequent incoming MIDI messages will be written to the queue
+      and can be retrieved with the \e getMessage function.
+  */
+  void cancelCallback();
+
+  //! Close an open MIDI connection (if one exists).
+  void closePort( void );
+
+  //! Return the number of available MIDI input ports.
+  unsigned int getPortCount();
+
+  //! Return a string identifier for the specified MIDI input port number.
+  /*!
+      An exception is thrown if an invalid port specifier is provided.
+  */
+  std::string getPortName( unsigned int portNumber = 0 );
+
+  //! Set the maximum number of MIDI messages to be saved in the queue.
+  /*!
+      If the queue size limit is reached, incoming messages will be
+      ignored.  The default limit is 1024.
+  */
+  void setQueueSizeLimit( unsigned int queueSize );
+
+  //! Specify whether certain MIDI message types should be queued or ignored during input.
+  /*!
+      By default, MIDI timing and active sensing messages are ignored
+      during message input because of their relative high data rates.
+      MIDI sysex messages are ignored by default as well.  Variable
+      values of "true" imply that the respective message type will be
+      ignored.
+  */
+  void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
+
+  //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds.
+  /*!
+      This function returns immediately whether a new message is
+      available or not.  A valid message is indicated by a non-zero
+      vector size.  An exception is thrown if an error occurs during
+      message retrieval or an input connection was not previously
+      established.
+  */
+  double getMessage( std::vector<unsigned char> *message );
+
+  // A MIDI structure used internally by the class to store incoming
+  // messages.  Each message represents one and only one MIDI message.
+  struct MidiMessage { 
+    std::vector<unsigned char> bytes; 
+    double timeStamp;
+
+    // Default constructor.
+    MidiMessage()
+      :bytes(3), timeStamp(0.0) {}
+  };
+
+  // The RtMidiInData structure is used to pass private class data to
+  // the MIDI input handling function or thread.
+  struct RtMidiInData {
+    std::queue<MidiMessage> queue;
+    unsigned int queueLimit;
+    unsigned char ignoreFlags;
+    bool doInput;
+    bool firstMessage;
+    void *apiData;
+    bool usingCallback;
+    void *userCallback;
+    void *userData;
+
+    // Default constructor.
+    RtMidiInData()
+      : queueLimit(1024), ignoreFlags(7), doInput(false), firstMessage(true),
+        apiData(0), usingCallback(false), userCallback(0), userData(0) {}
+  };
+
+ private:
+
+  void initialize( void );
+  RtMidiInData inputData_;
+
+};
+
+/**********************************************************************/
+/*! \class RtMidiOut
+    \brief A realtime MIDI output class.
+
+    This class provides a common, platform-independent API for MIDI
+    output.  It allows one to probe available MIDI output ports, to
+    connect to one such port, and to send MIDI bytes immediately over
+    the connection.  Create multiple instances of this class to
+    connect to more than one MIDI device at the same time.
+
+    by Gary P. Scavone, 2003-2004.
+*/
+/**********************************************************************/
+
+class RtMidiOut : public RtMidi
+{
+ public:
+
+  //! Default constructor.
+  /*!
+      An exception will be thrown if a MIDI system initialization error occurs.
+  */
+  RtMidiOut();
+
+  //! The destructor closes any open MIDI connections.
+  ~RtMidiOut();
+
+  //! Open a MIDI output connection.
+  /*!
+      An optional port number greater than 0 can be specified.
+      Otherwise, the default or first port found is opened.  An
+      exception is thrown if an error occurs while attempting to make
+      the port connection.
+  */
+  void openPort( unsigned int portNumber = 0 );
+
+  //! Close an open MIDI connection (if one exists).
+  void closePort();
+
+  //! Create a virtual output port to allow software connections (OS X and ALSA only).
+  /*!
+      This function creates a virtual MIDI output port to which other
+      software applications can connect.  This type of functionality
+      is currently only supported by the Macintosh OS-X and Linux ALSA
+      APIs (the function does nothing with the other APIs).  An
+      exception is thrown if an error occurs while attempting to create
+      the virtual port.
+  */
+  void openVirtualPort();
+
+  //! Return the number of available MIDI output ports.
+  unsigned int getPortCount();
+
+  //! Return a string identifier for the specified MIDI port type and number.
+  /*!
+      An exception is thrown if an invalid port specifier is provided.
+  */
+  std::string getPortName( unsigned int portNumber );
+
+  //! Immediately send a single message out an open MIDI output port.
+  /*!
+      An exception is thrown if an error occurs during output or an
+      output connection was not previously established.
+  */
+  void sendMessage( std::vector<unsigned char> *message );
+
+ private:
+
+  void initialize( void );
+};
+
+#endif

+ 1371 - 0
config.guess

@@ -0,0 +1,1371 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2004-02-26'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c
+	for c in cc gcc c89 ; do
+	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1
+	  if test $? = 0 ; then
+	     CC_FOR_BUILD="$c"; break
+	  fi
+	done
+	rm -f $dummy.c $dummy.o $dummy.rel
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# Netbsd (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	# Determine the machine/vendor (is the vendor relevant).
+	case "${UNAME_MACHINE}" in
+	    amiga) machine=m68k-unknown ;;
+	    arm32) machine=arm-unknown ;;
+	    atari*) machine=m68k-atari ;;
+	    sun3*) machine=m68k-sun ;;
+	    mac68k) machine=m68k-apple ;;
+	    macppc) machine=powerpc-apple ;;
+	    hp3[0-9][05]) machine=m68k-hp ;;
+	    ibmrt|romp-ibm) machine=romp-ibm ;;
+	    *) machine=${UNAME_MACHINE}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE}" in
+	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	cat <<EOF >$dummy.s
+	.data
+\$Lformat:
+	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+
+	.text
+	.globl main
+	.align 4
+	.ent main
+main:
+	.frame \$30,16,\$26,0
+	ldgp \$29,0(\$27)
+	.prologue 1
+	.long 0x47e03d80 # implver \$0
+	lda \$2,-1
+	.long 0x47e20c21 # amask \$2,\$1
+	lda \$16,\$Lformat
+	mov \$0,\$17
+	not \$1,\$18
+	jsr \$26,printf
+	ldgp \$29,0(\$26)
+	mov 0,\$16
+	jsr \$26,exit
+	.end main
+EOF
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+			0-0)
+				UNAME_MACHINE="alpha"
+				;;
+			1-0)
+				UNAME_MACHINE="alphaev5"
+				;;
+			1-1)
+				UNAME_MACHINE="alphaev56"
+				;;
+			1-101)
+				UNAME_MACHINE="alphapca56"
+				;;
+			2-303)
+				UNAME_MACHINE="alphaev6"
+				;;
+			2-307)
+				UNAME_MACHINE="alphaev67"
+				;;
+		esac
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    sun3*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD $dummy.c -o $dummy \
+	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+		rm -f $dummy.c $dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+              case "${HPUX_REV}" in
+                11.[0-9][0-9])
+                  if [ -x /usr/bin/getconf ]; then
+                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                        esac ;;
+                    esac
+                  fi ;;
+              esac
+              if [ "${HP_ARCH}" = "" ]; then
+              sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+	if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+	rm -f $dummy.c $dummy
+	fi ;;
+	esac
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    hppa*:OpenBSD:*:*)
+	echo hppa-unknown-openbsd
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE}
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3D:*:*:*)
+	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY-2:*:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i386-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	cat >$dummy.c <<EOF
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+int main (int argc, char *argv[]) {
+#else
+int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __MIPSEB__
+  printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+  printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	;;
+    ppc:Linux:*:*)
+	# Determine Lib Version
+	cat >$dummy.c <<EOF
+#include <features.h>
+#if defined(__GLIBC__)
+extern char __libc_version[];
+extern char __libc_release[];
+#endif
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+#if defined(__GLIBC__)
+  printf("%s %s\n", __libc_version, __libc_release);
+#else
+  printf("unknown\n");
+#endif
+  return 0;
+}
+EOF
+	LIBC=""
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		./$dummy | grep 1\.99 > /dev/null
+		if test "$?" = 0 ; then LIBC="libc1" ; fi
+	fi
+	rm -f $dummy.c $dummy
+	echo powerpc-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    alpha:Linux:*:*)
+	cat <<EOF >$dummy.s
+	  .data
+	  \$Lformat:
+		.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+	   .text
+		.globl main
+		.align 4
+		.ent main
+	    main:
+		.frame \$30,16,\$26,0
+		ldgp \$29,0(\$27)
+		.prologue 1
+		.long 0x47e03d80 # implver \$0
+		lda \$2,-1
+		.long 0x47e20c21 # amask \$2,\$1
+		lda \$16,\$Lformat
+		mov \$0,\$17
+		not \$1,\$18
+		jsr \$26,printf
+		ldgp \$29,0(\$26)
+		mov 0,\$16
+		jsr \$26,exit
+		.end main
+EOF
+	LIBC=""
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+		0-0)	UNAME_MACHINE="alpha" ;;
+		1-0)	UNAME_MACHINE="alphaev5" ;;
+		1-1)    UNAME_MACHINE="alphaev56" ;;
+		1-101)	UNAME_MACHINE="alphapca56" ;;
+		2-303)	UNAME_MACHINE="alphaev6" ;;
+		2-307)	UNAME_MACHINE="alphaev67" ;;
+		esac
+		objdump --private-headers $dummy | \
+		  grep ld.so.1 > /dev/null
+		if test "$?" = 0 ; then
+			LIBC="libc1"
+		fi
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	ld_supported_emulations=`cd /; ld --help 2>&1 \
+			 | sed -ne '/supported emulations:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported emulations: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_emulations" in
+	  i*86linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0
+		;;
+	  elf_i*86)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  i*86coff)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0
+		;;
+	esac
+	# Either a pre-BFD a.out linker (linux-gnuoldld)
+	# or one that does not give us useful --help.
+	# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+	# If ld does not provide *any* "supported emulations:"
+	# that means it is gnuoldld.
+	test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+	case "${UNAME_MACHINE}" in
+	i*86)
+	  VENDOR=pc;
+	  ;;
+	*)
+	  VENDOR=unknown;
+	  ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+    i*86:DYNIX/ptx:4*:*)
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:7*)
+        # Fixed at (any) Pentium or better
+        UNAME_MACHINE=i586
+        if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then
+	    echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
+	else
+	    echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+	fi
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	if test "${UNAME_MACHINE}" = "x86pc"; then
+		UNAME_MACHINE=pc
+	fi
+	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[KW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:

+ 1362 - 0
config.sub

@@ -0,0 +1,1362 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2004-02-26'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+	        | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+		| pyramid | mn10200 | mn10300 | tron | a29k \
+		| 580 | i960 | h8300 \
+		| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+		| hppa64 \
+		| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+		| alphaev6[78] \
+		| we32k | ns16k | clipper | i370 | sh | sh[34] \
+		| powerpc | powerpcle \
+		| 1750a | dsp16xx | pdp10 | pdp11 \
+		| mips16 | mips64 | mipsel | mips64el \
+		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
+		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+		| mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \
+		| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+		| v850 | c4x \
+		| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+		| pj | pjl | h8500)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	# FIXME: clean up the formatting here.
+	vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+	      | arm-*  | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+	      | xmp-* | ymp-* \
+	      | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+	      | hppa2.0n-* | hppa64-* \
+	      | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+	      | alphaev6[78]-* \
+	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+	      | clipper-* | orion-* \
+	      | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+	      | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+	      | mips16-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* \
+	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+	      | mipstx39-* | mipstx39el-* | mcore-* \
+	      | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+	      | [cjt]90-* \
+	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+	      | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+	      | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	[cjt]90)
+		basic_machine=${basic_machine}-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsel*-linux*)
+		basic_machine=mipsel-unknown
+		os=-linux-gnu
+		;;
+	mips*-linux*)
+		basic_machine=mips-unknown
+		os=-linux-gnu
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+	        ;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+	        ;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=t3e-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	mips)
+		if [ x$os = x-linux-gnu ]; then
+			basic_machine=mips-unknown
+		else
+			basic_machine=mips-mips
+		fi
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	c4x*)
+		basic_machine=c4x-none
+		os=-coff
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto*)
+		os=-nto-qnx
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-ns2 )
+	        os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+	        os=-mint
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	pdp10-*)
+		os=-tops20
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+        *-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:

+ 66 - 0
configure.ac

@@ -0,0 +1,66 @@
+# Process this file with autoconf to produce a configure script.
+AC_INIT(RtMidi, 1.0, gary@music.mcgill.ca, rtmidi)
+AC_CONFIG_SRCDIR(RtMidi.cpp)
+AC_CONFIG_FILES(tests/Makefile)
+
+# Fill GXX with something before test.
+AC_SUBST( GXX, ["no"] )
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX(g++ CC c++ cxx)
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/ioctl.h unistd.h)
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+# Check for debug
+AC_MSG_CHECKING(whether to compile debug version)
+AC_ARG_ENABLE(debug,
+  [  --enable-debug = enable various debug output],
+  [AC_SUBST( debug, [-D__RTMIDI_DEBUG__] ) AC_SUBST( cflags, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)],
+  [AC_SUBST( debug, [] ) AC_SUBST( cflags, [-O2] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)])
+
+# Check compiler and use -Wall if gnu.
+if [test $GXX = "yes" ;] then
+  AC_SUBST( warn, [-Wall] )
+fi
+
+# Checks for package options and external software
+AC_CANONICAL_HOST
+AC_MSG_CHECKING(for MIDI API)
+case $host in
+  *-*-linux*)
+  AC_SUBST( midi_api, [_D__LINUX_ALSA__] )
+  AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(RtMidi in Linux requires the ALSA asound library!))
+  # Checks for pthread library.
+  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!))
+  ;;
+
+  *-sgi*)
+  AC_SUBST( midi_api, ["-D__IRIX_MD__ -LANG:std -w"] )
+  AC_MSG_RESULT(using IRIX MD)
+  AC_CHECK_LIB(md, mdInit, , AC_MSG_ERROR(IRIX MIDI support requires the md library!) )
+  # Checks for pthread library.
+  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!))
+  ;;
+
+  *-apple*)
+  # Check for CoreAudio framework
+  AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [AC_SUBST( midi_api, [-D__MACOSX_CORE__] )], [AC_MSG_ERROR(CoreMIDI header files not found!)] )
+  AC_SUBST( frameworks, ["-framework CoreMIDI -framework CoreFoundation -framework CoreAudio"] )
+  ;;
+
+  *)
+  # Default case for unknown realtime systems.
+  AC_MSG_ERROR(Unknown system type for MIDI support!)
+  ;;
+esac
+
+# Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+
+AC_OUTPUT

+ 155 - 0
doc/doxygen/Doxyfile

@@ -0,0 +1,155 @@
+# Doxyfile 1.2.6
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = RtMidi
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = .
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CLASS_DIAGRAMS         = YES
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ENABLED_SECTIONS       = 
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+ALIASES                = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = NO
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = tutorial.txt ../../RtMidi.h ../../RtError.h
+FILE_PATTERNS          = 
+RECURSIVE              = NO
+EXCLUDE                = 
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = ../html
+HTML_HEADER            = header.html
+HTML_FOOTER            = footer.html
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = letter
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_PATH               = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
+CGI_NAME               = search.cgi
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = /usr/local/bin/
+EXT_DOC_PATHS          = 
+

+ 9 - 0
doc/doxygen/footer.html

@@ -0,0 +1,9 @@
+<HR>
+
+<table><tr><td><img src="../images/mcgill.gif" width=165></td>
+  <td>&copy;2003-2004 Gary P. Scavone, McGill University. All Rights Reserved.<br>
+  Maintained by Gary P. Scavone, gary at music.mcgill.ca</td></tr>
+</table>
+
+</BODY>
+</HTML>

+ 9 - 0
doc/doxygen/header.html

@@ -0,0 +1,9 @@
+<HTML>
+<HEAD>
+<TITLE>The RtMidi Tutorial</TITLE>
+<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+<CENTER>
+<a class="qindex" href="index.html">Tutorial</a> &nbsp; <a class="qindex" href="annotated.html">Class/Enum List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; </CENTER>
+<HR>

+ 415 - 0
doc/doxygen/tutorial.txt

@@ -0,0 +1,415 @@
+/*! \mainpage The RtMidi Tutorial
+
+<BODY BGCOLOR="white">
+
+<CENTER>\ref intro &nbsp;&nbsp; \ref download &nbsp;&nbsp; \ref start &nbsp;&nbsp; \ref error &nbsp;&nbsp; \ref probing &nbsp;&nbsp; \ref output &nbsp;&nbsp; \ref input &nbsp;&nbsp; \ref virtual &nbsp;&nbsp; \ref compiling &nbsp;&nbsp; \ref debug &nbsp;&nbsp; \ref apinotes &nbsp;&nbsp; \ref license</CENTER>
+
+\section intro Introduction
+
+RtMidi is a set of C++ classes (RtMidiIn and RtMidiOut) which provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA), Macintosh OS X, SGI, and Windows (Multimedia Library) operating systems.  RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software.  It was designed with the following goals:
+
+<UL>
+  <LI>object oriented C++ design</LI>
+  <LI>simple, common API across all supported platforms</LI>
+  <LI>only two header files and one source file for easy inclusion in programming projects</LI>
+  <LI>MIDI device enumeration</LI>
+</UL>
+
+MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut.  Each class instance supports only a single MIDI connection.  RtMidi does not provide timing functionality (i.e., output messages are sent immediately).  Input messages are timestamped with delta times in seconds (via a \c double floating point type).  MIDI data is passed to the user as raw bytes using an std::vector<unsigned char>.
+
+\section download Download
+
+Latest Release (17 September 2004): <A href="http://music.mcgill.ca/~gary/rtmidi/release/rtmidi-1.0.0.tar.gz">Version 1.0.0 (154 kB tar/gzipped)</A>
+
+\section start Getting Started
+
+The first thing that must be done when using RtMidi is to create an instance of the RtMidiIn or RtMidiOut subclasses.  RtMidi is an abstract base class, which itself cannot be instantiated.  Each default constructor attempts to establish any necessary "connections" with the underlying MIDI system.  RtMidi uses C++ exceptions to report errors, necessitating try/catch blocks around many member functions.  An RtError can be thrown during instantiation in some circumstances.  A warning message may also be reported if no MIDI devices are found during instantiation.  The RtMidi classes have been designed to work with "hot pluggable" or virtual (software) MIDI devices, making it is possible to connect or start MIDI devices after the classes have been instantiated.  The following code example demonstrates default object construction and destruction:
+
+\code
+
+#include "RtMidi.h"
+
+int main()
+{
+  RtMidiIn *midiin = 0;
+
+  // RtMidiIn constructor
+  try {
+    midiin = new RtMidiIn();
+  }
+  catch (RtError &error) {
+    // Handle the exception here
+    error.printMessage();
+  }
+
+  // Clean up
+  delete midiin;
+}
+\endcode
+
+Obviously, this example doesn't demonstrate any of the real functionality of RtMidi.  However, all uses of RtMidi must begin with construction and must end with class destruction.  Further, it is necessary that all class methods which can throw a C++ exception be called within a try/catch block.
+
+
+\section error Error Handling
+
+RtMidi uses a C++ exception handler called RtError, which is declared and defined in RtError.h.  The RtError class is quite simple but it does allow errors to be "caught" by RtError::Type.  Many RtMidi methods can "throw" an RtError, most typically if a driver error occurs or an invalid function argument is specified.  There are a number of cases within RtMidi where warning messages may be displayed but an exception is not thrown.  There is a protected RtMidi method, error(), which can be modified to globally control how these messages are handled and reported.  By default, error messages are not automatically displayed in RtMidi unless the preprocessor definition __RTMIDI_DEBUG__ is defined.  Messages associated with caught exceptions can be displayed with, for example, the RtError::printMessage() function.
+
+
+\section probing Probing Ports
+
+A programmer may wish to query the available MIDI ports before deciding which to use.  The following example outlines how this can be done.
+
+\code
+// midiinfo.cpp
+
+#include <iostream>
+#include "RtMidi.h"
+
+int main()
+{
+  RtMidiIn  *midiin = 0;
+  RtMidiOut *midiout = 0;
+
+  // RtMidiIn constructor
+  try {
+    midiin = new RtMidiIn();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check inputs.
+  unsigned int nPorts = midiin->getPortCount();
+  std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n";
+  std::string portName;
+  for ( unsigned int i=0; i<nPorts; i++ ) {
+    try {
+      portName = midiin->getPortName(i);
+    }
+    catch (RtError &error) {
+      error.printMessage();
+      goto cleanup;
+    }
+    std::cout << "  Input Port #" << i+1 << ": " << portName << '\n';
+  }
+
+  // RtMidiOut constructor
+  try {
+    midiout = new RtMidiOut();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check outputs.
+  nPorts = midiout->getPortCount();
+  std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n";
+  for ( unsigned int i=0; i<nPorts; i++ ) {
+    try {
+      portName = midiout->getPortName(i);
+    }
+    catch (RtError &error) {
+      error.printMessage();
+      goto cleanup;
+    }
+    std::cout << "  Output Port #" << i+1 << ": " << portName << '\n';
+  }
+  std::cout << '\n';
+
+  // Clean up
+ cleanup:
+  delete midiin;
+  delete midiout;
+
+  return 0;
+}
+\endcode
+
+\section output MIDI Output
+
+The RtMidiOut class provides simple functionality to immediately send messages over a MIDI connection.  No timing functionality is provided.
+
+In the following example, we omit necessary error checking and details regarding OS-dependent sleep functions.  For a complete example, see the \c midiout.cpp program in the \c tests directory.
+
+\code
+// midiout.cpp
+
+#include <iostream>
+#include "RtMidi.h"
+
+int main()
+{
+  RtMidiOut *midiout = new RtMidiOut();
+  std::vector<unsigned char> message;
+
+  // Check available ports.
+  unsigned int nPorts = midiout->getPortCount();
+  if ( nPorts == 0 ) {
+    std::cout << "No ports available!\n";
+    goto cleanup;
+  }
+
+  // Open first available port.
+  midiout->openPort( 0 );
+
+  // Send out a series of MIDI messages.
+
+  // Program change: 192, 5
+  message.push_back( 192 );
+  message.push_back( 5 );
+  midiout->sendMessage( &message );
+
+  // Control Change: 176, 7, 100 (volume)
+  message[0] = 176;
+  message[1] = 7;
+  message.push_back( 100 );
+  midiout->sendMessage( &message );
+
+  // Note On: 144, 64, 90
+  message[0] = 144;
+  message[1] = 64;
+  message[2] = 90;
+  midiout->sendMessage( &message );
+
+  SLEEP( 500 ); // Platform-dependent ... see example in tests directory.
+
+  // Note Off: 128, 64, 40
+  message[0] = 128;
+  message[1] = 64;
+  message[2] = 40;
+  midiout->sendMessage( &message );
+
+  // Clean up
+ cleanup:
+  delete midiout;
+
+  return 0;
+}
+\endcode
+
+
+\section input MIDI Input
+
+The RtMidiIn class uses an internal callback function or thread to receive incoming MIDI messages from a port or device.  These messages are then either queued and read by the user via calls to the RtMidiIn::getMessage() function or immediately passed to a user-specified callback function (which must be "registered" using the RtMidiIn::setCallback() function).  We'll provide examples of both usages.
+
+The RtMidiIn class provides the RtMidiIn::ignoreTypes() function to specify that certain MIDI message types be ignored.  By default, sysem exclusive, timing, and active sensing messages are ignored.
+
+\subsection qmidiin Queued MIDI Input
+
+The RtMidiIn::getMessage() function does not block.  If a MIDI message is available in the queue, it is copied to the user-provided \c std::vector<unsigned char> container.  When no MIDI message is available, the function returns an empty container.  The default maximum MIDI queue size is 1024 messages.  This value may be modified with the RtMidiIn::setQueueSizeLimit() function.  If the maximum queue size limit is reached, subsequent MIDI messages are discarded until the queue size is reduced.
+
+In the following example, we omit some necessary error checking and details regarding OS-dependent sleep functions.  For a more complete example, see the \c qmidiin.cpp program in the \c tests directory.
+
+\code
+// qmidiin.cpp
+
+#include <iostream>
+#include <signal.h>
+#include "RtMidi.h"
+
+bool done;
+static void finish(int ignore){ done = true; }
+
+int main()
+{
+  RtMidiIn *midiin = new RtMidiIn();
+  std::vector<unsigned char> message;
+  int nBytes, i;
+  double stamp;
+
+  // Check available ports.
+  unsigned int nPorts = midiin->getPortCount();
+  if ( nPorts == 0 ) {
+    std::cout << "No ports available!\n";
+    goto cleanup;
+  }
+  midiin->openPort( 0 );
+
+  // Don't ignore sysex, timing, or active sensing messages.
+  midiin->ignoreTypes( false, false, false );
+
+  // Install an interrupt handler function.
+  done = false;
+  (void) signal(SIGINT, finish);
+
+  // Periodically check input queue.
+  std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n";
+  while ( !done ) {
+    stamp = midiin->getMessage( &message );
+    nBytes = message.size();
+    for ( i=0; i<nBytes; i++ )
+      std::cout << "Byte " << i << " = " << (int)message[i] << ", ";
+    if ( nBytes > 0 )
+      std::cout << "stamp = " << stamp << '\n';
+
+    // Sleep for 10 milliseconds ... platform-dependent.
+    SLEEP( 10 );
+  }
+
+  // Clean up
+ cleanup:
+  delete midiin;
+
+  return 0;
+}
+\endcode
+
+\subsection cmidiin MIDI Input with User Callback
+
+When set, a user-provided callback function will be invoked after the input of a complete MIDI message.  It is possible to provide a pointer to user data which can be accessed in the callback function (not shown here).  It is necessary to set the callback function immediately after opening the port to avoid having incoming messages written to the queue (which is not emptied when a callback function is set).  If you are worried about this happening, you can check the queue using the RtMidi::getMessage() function to verify it is empty (after the callback function is set).
+
+In the following example, we omit some necessary error checking.  For a more complete example, see the \c cmidiin.cpp program in the \c tests directory.
+
+\code
+// cmidiin.cpp
+
+#include <iostream>
+#include "RtMidi.h"
+
+void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData )
+{
+  unsigned int nBytes = message->size();
+  for ( unsigned int i=0; i<nBytes; i++ )
+    std::cout << "Byte " << i << " = " << (int)message->at(i) << ", ";
+  if ( nBytes > 0 )
+    std::cout << "stamp = " << deltatime << '\n';
+}
+
+int main()
+{
+  RtMidiIn *midiin = new RtMidiIn();
+
+  // Check available ports.
+  unsigned int nPorts = midiin->getPortCount();
+  if ( nPorts == 0 ) {
+    std::cout << "No ports available!\n";
+    goto cleanup;
+  }
+
+  midiin->openPort( 0 );
+
+  // Set our callback function.  This should be done immediately after
+  // opening the port to avoid having incoming messages written to the
+  // queue.
+  midiin->setCallback( &mycallback );
+
+  // Don't ignore sysex, timing, or active sensing messages.
+  midiin->ignoreTypes( false, false, false );
+
+  std::cout << "\nReading MIDI input ... press <enter> to quit.\n";
+  char input;
+  std::cin.get(input);
+
+  // Clean up
+ cleanup:
+  delete midiin;
+
+  return 0;
+}
+\endcode
+
+\section virtual Virtual Ports
+
+The Linux ALSA and Macintosh CoreMIDI APIs allow for the establishment of virtual input and output MIDI ports to which other software clients can connect.  RtMidi incorporates this functionality with the RtMidiIn::openVirtualPort() and RtMidiOut::openVirtualPort() functions.  Any messages sent with the RtMidiOut::sendMessage() function will also be transmitted through an open virtual output port.  If a virtual input port is open and a user callback function is set, the callback function will be invoked when messages arrive via that port.  If a callback function is not set, the user must poll the input queue to check whether messages have arrived.  No notification is provided for the establishment of a client connection via a virtual port.
+
+\section compiling Compiling
+
+In order to compile RtMidi for a specific OS and API, it is necessary to supply the appropriate preprocessor definition and library within the compiler statement:
+<P>
+
+<TABLE BORDER=2 COLS=5 WIDTH="100%">
+<TR BGCOLOR="beige">
+  <TD WIDTH="5%"><B>OS:</B></TD>
+  <TD WIDTH="5%"><B>Audio API:</B></TD>
+  <TD WIDTH="5%"><B>Preprocessor Definition:</B></TD>
+  <TD WIDTH="5%"><B>Library or Framework:</B></TD>
+  <TD><B>Example Compiler Statement:</B></TD>
+</TR>
+<TR>
+  <TD>Linux</TD>
+  <TD>ALSA</TD>
+  <TD>__LINUX_ALSA__</TD>
+  <TD><TT>asound, pthread</TT></TD>
+  <TD><TT>g++ -Wall -D__LINUX_ALSA__ -o midiinfo midiinfo.cpp RtMidi.cpp -lasound -lpthread</TT></TD>
+</TR>
+<TR>
+  <TD>Macintosh OS X</TD>
+  <TD>CoreAudio</TD>
+  <TD>__MACOSX_CORE__</TD>
+  <TD><TT>pthread, stdc++, CoreAudio</TT></TD>
+  <TD><TT>g++ -Wall -D__MACOSX_CORE__ -o midiinfo midiinfo.cpp RtMidi.cpp -framework CoreMidi -lpthread</TT></TD>
+</TR>
+<TR>
+  <TD>Irix</TD>
+  <TD>MD</TD>
+  <TD>__IRIX_MD__</TD>
+  <TD><TT>md, pthread</TT></TD>
+  <TD><TT>CC -Wall -D__IRIX_MD__ -o midiinfo midiinfo.cpp RtMidi.cpp -laudio -lpthread</TT></TD>
+</TR>
+<TR>
+  <TD>Windows</TD>
+  <TD>Multimedia Library</TD>
+  <TD>__WINDOWS_MM__</TD>
+  <TD><TT>winmm.lib, multithreaded</TT></TD>
+  <TD><I>compiler specific</I></TD>
+</TR>
+</TABLE>
+<P>
+
+The example compiler statements above could be used to compile the <TT>probe.cpp</TT> example file, assuming that <TT>midiinfo.cpp</TT>, <TT>RtMidi.h</TT>, <tt>RtError.h</tt>, and <TT>RtMidi.cpp</TT> all exist in the same directory.
+
+\section debug Debugging
+
+If you are having problems getting RtMidi to run on your system, try passing the preprocessor definition <TT>__RTMIDI_DEBUG__</TT> to the compiler (or uncomment the definition at the bottom of RtMidi.h).  A variety of warning messages will be displayed which may help in determining the problem.  Also try using the programs included in the <tt>test</tt> directory.  The program <tt>midiinfo</tt> displays the queried capabilities of all MIDI ports found.
+
+\section apinotes API Notes
+
+RtMidi is designed to provide a common API across the various supported operating systems and audio libraries.  Despite that, some issues should be mentioned with regard to each.
+
+\subsection linux Linux:
+
+RtMidi for Linux was developed using the Fedora distribution.  A decision was made to not include support for the OSS API because the OSS API provides such limited functionality and because <A href="http://www.alsa-project.org/">ALSA</A> support is now incorporated in the Linux kernel.  RtMidi uses the ALSA sequencer API, which allows for virtual software input and output ports. 
+
+\subsection macosx Macintosh OS X (CoreAudio):
+
+The Apple CoreMidi API allows for the establishment of virtual input and output ports to which other software applications can connect.
+
+\subsection irix Irix (SGI):
+
+The Irix version of RtMidi was written and tested on an SGI Indy running Irix version 6.5.4 and the MD audio library.
+
+\subsection windowsds Windows (Multimedia Library):
+
+The Windows Multimedia library MIDI calls used in RtMidi do not make use of streaming functionality.  RtMidi was originally developed with Visual C++ version 6.0.
+
+\section license License
+
+    RtMidi: realtime MIDI i/o C++ classes<BR>
+    Copyright (c) 2003-2004 Gary P. Scavone
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation files
+    (the "Software"), to deal in the Software without restriction,
+    including without limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of the Software,
+    and to permit persons to whom the Software is furnished to do so,
+    subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    Any person wishing to distribute modifications to the Software is
+    requested to send the modifications to the original developer so that
+    they can be incorporated into the canonical version.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/

BIN
doc/images/ccrma.gif


BIN
doc/images/mcgill.gif


+ 7 - 0
doc/release.txt

@@ -0,0 +1,7 @@
+RtMidi - a set of C++ classes which provide a common API for realtime MIDI input/output across Linux (ALSA), SGI, Macintosh OS X (CoreMidi), and Windows (Multimedia) operating systems.
+
+By Gary P. Scavone, 2003-2004.
+
+v1.0.0: (17 September 2004)
+- first release of new independent class with both input and output functionality
+

+ 155 - 0
doxygen/Doxyfile

@@ -0,0 +1,155 @@
+# Doxyfile 1.2.6
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = STK
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = .
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CLASS_DIAGRAMS         = YES
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+ENABLED_SECTIONS       = 
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+ALIASES                = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = NO
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = . ..
+FILE_PATTERNS          = *.txt *.h *.cpp
+RECURSIVE              = NO
+EXCLUDE                = ../../src/asio
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_HEADER            = header.html
+HTML_FOOTER            = footer.html
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = YES
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = letter
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               =
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_PATH               = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
+CGI_NAME               = search.cgi
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = /usr/local/bin/
+EXT_DOC_PATHS          = 
+

+ 9 - 0
doxygen/footer.html

@@ -0,0 +1,9 @@
+<HR>
+
+<table>
+  <tr><td><A HREF="http://www-ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
+  <tr><td>&copy;1995-2002 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
+</table>
+
+</BODY>
+</HTML>

+ 10 - 0
doxygen/header.html

@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>The Synthesis ToolKit in C++ (STK)</TITLE>
+<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+<CENTER>
+<img src="princeton.gif"> &nbsp; <img src="ccrma.gif"><P>
+<a class="qindex" href="index.html">Home</a> &nbsp; <a class="qindex" href="information.html">Information</a> &nbsp; <a class="qindex" href="classes.html">Classes</a> &nbsp; <a class="qindex" href="download.html">Download</a> &nbsp; <a class="qindex" href="usage.html">Usage</a> &nbsp; <a class="qindex" href="maillist.html">Mail List</a> &nbsp; <a class="qindex" href="system.html">Requirements</a> &nbsp; <a class="qindex" href="links.html">Links</a> &nbsp; <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
+<HR>

+ 0 - 0
install.sh


+ 56 - 0
readme

@@ -0,0 +1,56 @@
+RtMidi - a set of C++ classes which provide a common API for realtime MIDI input/output across Linux (ALSA), SGI, Macintosh OS X (CoreMidi), and Windows (Multimedia) operating systems.
+
+By Gary P. Scavone, 2003-2004.
+
+This distribution of RtMidi contains the following:
+
+doc:      RtMidi documentation (see doc/html/index.html)
+tests:    example RtMidi programs
+
+On unix systems, type "./configure" in the top level directory, then "make" in the tests/ directory to compile the test programs.  In Windows, open the Visual C++ workspace file located in the tests/ directory.
+
+OVERVIEW:
+
+RtMidi is a set of C++ classes (RtMidiIn and RtMidiOut) which provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA), Macintosh OS X, SGI, and Windows (Multimedia Library) operating systems.  RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software.  It was designed with the following goals:
+
+  - object oriented C++ design
+  - simple, common API across all supported platforms
+  - only two header files and one source file for easy inclusion in programming projects
+  - MIDI device enumeration
+
+MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut.  Each class instance supports only a single MIDI connection.  RtMidi does not provide timing functionality (i.e., output messages are sent immediately).  Input messages are timestamped with delta times in seconds (via a double floating point type).  MIDI data is passed to the user as raw bytes using an std::vector<unsigned char>.
+
+FURTHER READING:
+
+For complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/.
+
+
+LEGAL AND ETHICAL:
+
+The RtMidi license is similar to the the MIT License, with the added "feature" that modifications be sent to the developer.
+
+    RtMidi: realtime MIDI i/o C++ classes
+    Copyright (c) 2003-2004 Gary P. Scavone
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation files
+    (the "Software"), to deal in the Software without restriction,
+    including without limitation the rights to use, copy, modify, merge,
+    publish, distribute, sublicense, and/or sell copies of the Software,
+    and to permit persons to whom the Software is furnished to do so,
+    subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    Any person wishing to distribute modifications to the Software is
+    requested to send the modifications to the original developer so that
+    they can be incorporated into the canonical version.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 0
tests/Debug/.placeholder


+ 43 - 0
tests/Makefile.in

@@ -0,0 +1,43 @@
+### RtMidi tests Makefile - for various flavors of unix
+
+PROGRAMS = midiinfo midiout qmidiin cmidiin
+RM = /bin/rm
+SRC_PATH = ../
+INCLUDE = ../
+OBJECT_PATH = @object_path@
+vpath %.o $(OBJECT_PATH)
+
+OBJECTS	=	RtMidi.o
+
+CC       = @CXX@
+DEFS     = @debug@
+DEFS    += @midi_api@
+CFLAGS   = @cflags@
+CFLAGS  += @warn@ -I$(INCLUDE)
+LIBRARY  = @LIBS@
+LIBRARY += @frameworks@
+
+%.o : $(SRC_PATH)/%.cpp
+	$(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@
+
+all : $(PROGRAMS)
+
+midiinfo : midiinfo.cpp $(OBJECTS)
+	$(CC) $(CFLAGS) $(DEFS) -o midiinfo midiinfo.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
+
+midiout : midiout.cpp $(OBJECTS)
+	$(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
+
+qmidiin : qmidiin.cpp $(OBJECTS)
+	$(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
+
+cmidiin : cmidiin.cpp $(OBJECTS)
+	$(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
+
+clean : 
+	-rm $(OBJECT_PATH)/*.o
+	-rm $(PROGRAMS)
+	-rm -f *~
+
+strip : 
+	strip $(PROGRAMS)

+ 0 - 0
tests/Release/.placeholder


+ 65 - 0
tests/RtMidi.dsw

@@ -0,0 +1,65 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "cmidiin"=.\cmidiin.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "midiinfo"=.\midiinfo.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "midiout"=.\midiout.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "qmidiin"=.\qmidiin.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 81 - 0
tests/cmidiin.cpp

@@ -0,0 +1,81 @@
+//*****************************************//
+//  cmidiin.cpp
+//  by Gary Scavone, 2003-2004.
+//
+//  Simple program to test MIDI input and
+//  use of a user callback function.
+//
+//*****************************************//
+
+#include <iostream>
+#include "RtMidi.h"
+
+void usage(void) {
+  // Error function in case of incorrect command-line
+  // argument specifications.
+  std::cout << "\nuseage: cmidiin <port>\n";
+  std::cout << "    where port = the device to use (default = 0).\n\n";
+  exit(0);
+}
+
+void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData )
+{
+  unsigned int nBytes = message->size();
+  for ( unsigned int i=0; i<nBytes; i++ )
+    std::cout << "Byte " << i << " = " << (int)message->at(i) << ", ";
+  if ( nBytes > 0 )
+    std::cout << "stamp = " << deltatime << '\n';
+}
+
+int main(int argc, char *argv[])
+{
+  RtMidiIn *midiin = 0;
+
+  // Minimal command-line check.
+  if ( argc > 2 ) usage();
+
+  // RtMidiIn constructor
+  try {
+    midiin = new RtMidiIn();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check available ports vs. specified.
+  unsigned int port = 0;
+  unsigned int nPorts = midiin->getPortCount();
+  if ( argc == 2 ) port = (unsigned int) atoi( argv[1] );
+  if ( port >= nPorts ) {
+    delete midiin;
+    std::cout << "Invalid port specifier!\n";
+    usage();
+  }
+
+  try {
+    midiin->openPort( port );
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    goto cleanup;
+  }
+
+  // Set our callback function.  This should be done immediately after
+  // opening the port to avoid having incoming messages written to the
+  // queue instead of sent to the callback function.
+  midiin->setCallback( &mycallback );
+
+  // Don't ignore sysex, timing, or active sensing messages.
+  midiin->ignoreTypes( false, false, false );
+
+  std::cout << "\nReading MIDI input ... press <enter> to quit.\n";
+  char input;
+  std::cin.get(input);
+
+  // Clean up
+ cleanup:
+  delete midiin;
+
+  return 0;
+}

+ 114 - 0
tests/cmidiin.dsp

@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="cmidiin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=cmidiin - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cmidiin.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cmidiin.mak" CFG="cmidiin - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "cmidiin - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "cmidiin - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "cmidiin - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "cmidiin___Win32_Release"
+# PROP BASE Intermediate_Dir "cmidiin___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "cmidiin - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "cmidiin___Win32_Debug"
+# PROP BASE Intermediate_Dir "cmidiin___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "cmidiin - Win32 Release"
+# Name "cmidiin - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\cmidiin.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\RtError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

+ 33 - 0
tests/cmidiin.plg

@@ -0,0 +1,33 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: cmidiin - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "c:\windows\TEMP\RSP5012.TMP" with contents
+[
+/nologo /ML /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /Fp"Release/cmidiin.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c 
+"C:\gary\rtmidi\RtMidi.cpp"
+]
+Creating command line "cl.exe @c:\windows\TEMP\RSP5012.TMP" 
+Creating temporary file "c:\windows\TEMP\RSP5013.TMP" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"cmidiin.pdb" /machine:I386 /out:"cmidiin.exe" 
+.\Release\RtMidi.obj
+.\Release\cmidiin.obj
+]
+Creating command line "link.exe @c:\windows\TEMP\RSP5013.TMP"
+<h3>Output Window</h3>
+Compiling...
+RtMidi.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+cmidiin.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>

+ 70 - 0
tests/midiinfo.cpp

@@ -0,0 +1,70 @@
+// midiinfo.cpp
+//
+// Simple program to check MIDI inputs and outputs.
+//
+// by Gary Scavone, 2003-2004.
+
+#include <iostream>
+#include "RtMidi.h"
+
+int main()
+{
+  RtMidiIn  *midiin = 0;
+  RtMidiOut *midiout = 0;
+
+  // RtMidiIn constructor
+  try {
+    midiin = new RtMidiIn();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check inputs.
+  unsigned int nPorts = midiin->getPortCount();
+  std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n";
+  std::string portName;
+  unsigned int i;
+  for ( i=0; i<nPorts; i++ ) {
+    try {
+      portName = midiin->getPortName(i);
+    }
+    catch (RtError &error) {
+      error.printMessage();
+      goto cleanup;
+    }
+    std::cout << "  Input Port #" << i+1 << ": " << portName << '\n';
+  }
+
+  // RtMidiOut constructor
+  try {
+    midiout = new RtMidiOut();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check outputs.
+  nPorts = midiout->getPortCount();
+  std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n";
+  for ( i=0; i<nPorts; i++ ) {
+    try {
+      portName = midiout->getPortName(i);
+    }
+    catch (RtError &error) {
+      error.printMessage();
+      goto cleanup;
+    }
+    std::cout << "  Output Port #" << i+1 << ": " << portName << '\n';
+  }
+  std::cout << '\n';
+
+  // Clean up
+ cleanup:
+  delete midiin;
+  delete midiout;
+
+  return 0;
+}

+ 114 - 0
tests/midiinfo.dsp

@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="midiinfo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=midiinfo - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "midiinfo.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "midiinfo.mak" CFG="midiinfo - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "midiinfo - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "midiinfo - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "midiinfo - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "midiinfo - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "midiinfo - Win32 Release"
+# Name "midiinfo - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\midiinfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\RtError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

+ 25 - 0
tests/midiinfo.plg

@@ -0,0 +1,25 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: midiinfo - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "c:\windows\TEMP\RSP51B0.TMP" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"midiinfo.pdb" /machine:I386 /out:"midiinfo.exe" 
+.\Release\midiinfo.obj
+.\Release\RtMidi.obj
+]
+Creating command line "link.exe @c:\windows\TEMP\RSP51B0.TMP"
+<h3>Output Window</h3>
+Linking...
+
+
+
+<h3>Results</h3>
+midiinfo.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>

+ 106 - 0
tests/midiout.cpp

@@ -0,0 +1,106 @@
+//*****************************************//
+//  midiout.cpp
+//  by Gary Scavone, 2003-2004.
+//
+//  Simple program to test MIDI output.
+//
+//*****************************************//
+
+#include <iostream>
+#include "RtMidi.h"
+
+// Platform-dependent sleep routines.
+#if defined(__WINDOWS_MM__)
+  #include <windows.h>
+  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 
+#else // Unix variants
+  #include <unistd.h>
+  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
+#endif
+
+void usage(void) {
+  // Error function in case of incorrect command-line
+  // argument specifications.
+  std::cout << "\nuseage: midiout <port>\n";
+  std::cout << "    where port = the device to use (default = 0).\n\n";
+  exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+  RtMidiOut *midiout = 0;
+  std::vector<unsigned char> message;
+
+  // Minimal command-line check.
+  if ( argc > 2 ) usage();
+
+  // RtMidiOut constructor
+  try {
+    midiout = new RtMidiOut();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check available ports vs. specified.
+  unsigned int port = 0;
+  unsigned int nPorts = midiout->getPortCount();
+  if ( argc == 2 ) port = (unsigned int) atoi( argv[1] );
+  if ( port >= nPorts ) {
+    delete midiout;
+    std::cout << "Invalid port specifier!\n";
+    usage();
+  }
+
+  try {
+    midiout->openPort( port );
+    //midiout->openVirtualPort();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    goto cleanup;
+  }
+
+  // Send out a series of MIDI messages.
+
+  // Program change: 192, 5
+  message.push_back( 192 );
+  message.push_back( 5 );
+  midiout->sendMessage( &message );
+
+  // Control Change: 176, 7, 100 (volume)
+  message[0] = 176;
+  message[1] = 7;
+  message.push_back( 100 );
+  midiout->sendMessage( &message );
+
+  // Note On: 144, 64, 90
+  message[0] = 144;
+  message[1] = 64;
+  message[2] = 90;
+  midiout->sendMessage( &message );
+
+  SLEEP( 500 );
+
+  // Note Off: 128, 64, 40
+  message[0] = 128;
+  message[1] = 64;
+  message[2] = 40;
+  midiout->sendMessage( &message );
+
+  // Sysex: 240, 67, 16, 4, 3, 2, 247
+  message[0] = 240;
+  message[1] = 67;
+  message[2] = 4;
+  message.push_back( 3 );
+  message.push_back( 2 );
+  message.push_back( 247 );
+  midiout->sendMessage( &message );
+
+  // Clean up
+ cleanup:
+  delete midiout;
+
+  return 0;
+}

+ 114 - 0
tests/midiout.dsp

@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="midiout" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=midiout - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "midiout.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "midiout.mak" CFG="midiout - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "midiout - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "midiout - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "midiout - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "midiout___Win32_Release"
+# PROP BASE Intermediate_Dir "midiout___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "midiout - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "midiout___Win32_Debug"
+# PROP BASE Intermediate_Dir "midiout___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "midiout - Win32 Release"
+# Name "midiout - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\midiout.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\RtError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

+ 33 - 0
tests/midiout.plg

@@ -0,0 +1,33 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: midiout - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "c:\windows\TEMP\RSP5250.TMP" with contents
+[
+/nologo /ML /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /Fp"Release/midiout.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c 
+"C:\gary\rtmidi\tests\midiout.cpp"
+]
+Creating command line "cl.exe @c:\windows\TEMP\RSP5250.TMP" 
+Creating temporary file "c:\windows\TEMP\RSP5251.TMP" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"midiout.pdb" /machine:I386 /out:"midiout.exe" 
+.\Release\RtMidi.obj
+.\Release\midiout.obj
+]
+Creating command line "link.exe @c:\windows\TEMP\RSP5251.TMP"
+<h3>Output Window</h3>
+Compiling...
+midiout.cpp
+Linking...
+
+
+
+<h3>Results</h3>
+midiout.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>

+ 97 - 0
tests/qmidiin.cpp

@@ -0,0 +1,97 @@
+//*****************************************//
+//  qmidiin.cpp
+//  by Gary Scavone, 2003-2004.
+//
+//  Simple program to test MIDI input and
+//  retrieval from the queue.
+//
+//*****************************************//
+
+#include <iostream>
+#include <signal.h>
+#include "RtMidi.h"
+
+// Platform-dependent sleep routines.
+#if defined(__WINDOWS_MM__)
+  #include <windows.h>
+  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 
+#else // Unix variants
+  #include <unistd.h>
+  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
+#endif
+
+bool done;
+static void finish(int ignore){ done = true; }
+
+void usage(void) {
+  // Error function in case of incorrect command-line
+  // argument specifications.
+  std::cout << "\nuseage: qmidiin <port>\n";
+  std::cout << "    where port = the device to use (default = 0).\n\n";
+  exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+  RtMidiIn *midiin = 0;
+  std::vector<unsigned char> message;
+  int nBytes, i;
+  double stamp;
+
+  // Minimal command-line check.
+  if ( argc > 2 ) usage();
+
+  // RtMidiIn constructor
+  try {
+    midiin = new RtMidiIn();
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    exit(EXIT_FAILURE);
+  }
+
+  // Check available ports vs. specified.
+  unsigned int port = 0;
+  unsigned int nPorts = midiin->getPortCount();
+  if ( argc == 2 ) port = (unsigned int) atoi( argv[1] );
+  if ( port >= nPorts ) {
+    delete midiin;
+    std::cout << "Invalid port specifier!\n";
+    usage();
+  }
+
+  try {
+    midiin->openPort( port );
+  }
+  catch (RtError &error) {
+    error.printMessage();
+    goto cleanup;
+  }
+
+  // Don't ignore sysex, timing, or active sensing messages.
+  midiin->ignoreTypes( false, false, false );
+
+  // Install an interrupt handler function.
+  done = false;
+  (void) signal(SIGINT, finish);
+
+  // Periodically check input queue.
+  std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n";
+  while ( !done ) {
+    stamp = midiin->getMessage( &message );
+    nBytes = message.size();
+    for ( i=0; i<nBytes; i++ )
+      std::cout << "Byte " << i << " = " << (int)message[i] << ", ";
+    if ( nBytes > 0 )
+      std::cout << "stamp = " << stamp << '\n';
+
+    // Sleep for 10 milliseconds.
+    SLEEP( 10 );
+  }
+
+  // Clean up
+ cleanup:
+  delete midiin;
+
+  return 0;
+}

+ 114 - 0
tests/qmidiin.dsp

@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="qmidiin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=qmidiin - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "qmidiin.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "qmidiin.mak" CFG="qmidiin - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "qmidiin - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "qmidiin - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "qmidiin - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "qmidiin___Win32_Release"
+# PROP BASE Intermediate_Dir "qmidiin___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "qmidiin - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "qmidiin___Win32_Debug"
+# PROP BASE Intermediate_Dir "qmidiin___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "qmidiin - Win32 Release"
+# Name "qmidiin - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\qmidiin.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\RtError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RtMidi.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project

+ 25 - 0
tests/qmidiin.plg

@@ -0,0 +1,25 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: qmidiin - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "c:\windows\TEMP\RSP5122.TMP" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /incremental:no /pdb:"qmidiin.pdb" /machine:I386 /out:"qmidiin.exe" 
+.\Release\qmidiin.obj
+.\Release\RtMidi.obj
+]
+Creating command line "link.exe @c:\windows\TEMP\RSP5122.TMP"
+<h3>Output Window</h3>
+Linking...
+
+
+
+<h3>Results</h3>
+qmidiin.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>