aboutsummaryrefslogtreecommitdiff
path: root/src/midiio
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2005-11-10 05:52:11 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2005-11-10 05:52:11 +0000
commitceac394c2133d44e81db2eb633ff54a9ad6ce7c5 (patch)
treeadc534407af80a976263c907897907cb13ef1c82 /src/midiio
This commit was generated by cvs2svn to compensate for changes in r3865,svn2git-root
which included commits to RCS files with non-trunk default branches. svn path=/trunk/extensions/gripd/; revision=3866
Diffstat (limited to 'src/midiio')
-rw-r--r--src/midiio/include/Array.cpp378
-rw-r--r--src/midiio/include/Array.h67
-rw-r--r--src/midiio/include/CircularBuffer.cpp291
-rw-r--r--src/midiio/include/CircularBuffer.h66
-rw-r--r--src/midiio/include/Collection.cpp355
-rw-r--r--src/midiio/include/Collection.h70
-rw-r--r--src/midiio/include/FileIO.h148
-rw-r--r--src/midiio/include/MidiFile.h108
-rw-r--r--src/midiio/include/MidiFileWrite.h61
-rw-r--r--src/midiio/include/MidiIO.h58
-rw-r--r--src/midiio/include/MidiInPort.h98
-rw-r--r--src/midiio/include/MidiInPort_alsa.h107
-rw-r--r--src/midiio/include/MidiInPort_alsa05.h107
-rw-r--r--src/midiio/include/MidiInPort_linux.h94
-rw-r--r--src/midiio/include/MidiInPort_oss.h105
-rw-r--r--src/midiio/include/MidiInPort_unsupported.h89
-rw-r--r--src/midiio/include/MidiInPort_visual.h114
-rw-r--r--src/midiio/include/MidiInput.h53
-rw-r--r--src/midiio/include/MidiMessage.h78
-rw-r--r--src/midiio/include/MidiOutPort.h92
-rw-r--r--src/midiio/include/MidiOutPort_alsa.h79
-rw-r--r--src/midiio/include/MidiOutPort_linux.h80
-rw-r--r--src/midiio/include/MidiOutPort_oss.h75
-rw-r--r--src/midiio/include/MidiOutPort_unsupported.h71
-rw-r--r--src/midiio/include/MidiOutPort_visual.h75
-rw-r--r--src/midiio/include/MidiOutput.h140
-rw-r--r--src/midiio/include/MidiPort.h49
-rw-r--r--src/midiio/include/Options.h106
-rw-r--r--src/midiio/include/Options_private.h73
-rw-r--r--src/midiio/include/Sequencer_alsa.h139
-rw-r--r--src/midiio/include/Sequencer_oss.h92
-rw-r--r--src/midiio/include/SigTimer.h104
-rw-r--r--src/midiio/include/Voice.h70
-rw-r--r--src/midiio/include/gminstruments.h251
-rw-r--r--src/midiio/include/midichannels.h42
-rw-r--r--src/midiio/include/mididefines.h34
-rw-r--r--src/midiio/include/midiiolib.h57
-rw-r--r--src/midiio/include/notenames.h219
-rw-r--r--src/midiio/include/sigConfiguration.h100
-rw-r--r--src/midiio/src/FileIO.cpp761
-rw-r--r--src/midiio/src/MidiFile.cpp1200
-rw-r--r--src/midiio/src/MidiFileWrite.cpp259
-rw-r--r--src/midiio/src/MidiIO.cpp283
-rw-r--r--src/midiio/src/MidiInPort_alsa.cpp1038
-rw-r--r--src/midiio/src/MidiInPort_alsa05.cpp995
-rw-r--r--src/midiio/src/MidiInPort_linux.cpp491
-rw-r--r--src/midiio/src/MidiInPort_oss.cpp1036
-rw-r--r--src/midiio/src/MidiInPort_unsupported.cpp487
-rw-r--r--src/midiio/src/MidiInPort_visual.cpp1267
-rw-r--r--src/midiio/src/MidiInput.cpp224
-rw-r--r--src/midiio/src/MidiMessage.cpp406
-rw-r--r--src/midiio/src/MidiOutPort_alsa.cpp469
-rw-r--r--src/midiio/src/MidiOutPort_linux.cpp381
-rw-r--r--src/midiio/src/MidiOutPort_oss.cpp462
-rw-r--r--src/midiio/src/MidiOutPort_unsupported.cpp402
-rw-r--r--src/midiio/src/MidiOutPort_visual.cpp532
-rw-r--r--src/midiio/src/MidiOutput.cpp1082
-rw-r--r--src/midiio/src/MidiPort.cpp189
-rw-r--r--src/midiio/src/Options.cpp887
-rw-r--r--src/midiio/src/Options_private.cpp358
-rw-r--r--src/midiio/src/Sequencer_alsa.cpp643
-rw-r--r--src/midiio/src/Sequencer_alsa05.cpp518
-rw-r--r--src/midiio/src/Sequencer_oss.cpp809
-rw-r--r--src/midiio/src/SigTimer.cpp498
-rw-r--r--src/midiio/src/Voice.cpp334
65 files changed, 20406 insertions, 0 deletions
diff --git a/src/midiio/include/Array.cpp b/src/midiio/include/Array.cpp
new file mode 100644
index 0000000..044ed2d
--- /dev/null
+++ b/src/midiio/include/Array.cpp
@@ -0,0 +1,378 @@
+//
+// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Sun May 11 20:41:28 GMT-0800 1997
+// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function)
+// Filename: ...sig/maint/code/base/Array/Array.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Array.cpp
+// Syntax: C++
+//
+// Description: An array which can grow dynamically. Array is derived from
+// the Collection class and adds various mathematical operators
+// to the Collection class. The Array template class is used for
+// storing numbers of any type which can be added, multiplied
+// and divided into one another.
+//
+
+#ifndef _ARRAY_CPP_INCLUDED
+#define _ARRAY_CPP_INCLUDED
+
+#include "Array.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+//////////////////////////////
+//
+// Array::Array
+//
+
+template<class type>
+Array<type>::Array(void) : Collection<type>(4) { }
+
+template<class type>
+Array<type>::Array(int arraySize) : Collection<type>(arraySize) { }
+
+template<class type>
+Array<type>::Array(Array<type>& anArray) : Collection<type>(anArray) { }
+
+template<class type>
+Array<type>::Array(int arraySize, type *anArray) :
+ Collection<type>(arraySize, anArray) { }
+
+
+
+
+//////////////////////////////
+//
+// Array::~Array
+//
+
+template<class type>
+Array<type>::~Array() { }
+
+
+
+//////////////////////////////
+//
+// Array::setAll -- sets the contents of each element to the
+// specified value
+//
+
+template<class type>
+void Array<type>::setAll(type aValue) {
+ for (int i=0; i<getSize(); i++) {
+ array[i] = aValue;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Array::sum
+//
+
+template<class type>
+type Array<type>::sum(void) {
+ type theSum = 0;
+ for (int i=0; i<getSize(); i++) {
+ theSum += array[i];
+ }
+ return theSum;
+}
+
+template<class type>
+type Array<type>::sum(int loIndex, int hiIndex) {
+ type theSum = 0;
+ for (int i=loIndex; i<=hiIndex; i++) {
+ theSum += array[i];
+ }
+ return theSum;
+}
+
+
+
+//////////////////////////////
+//
+// Array::zero(-1, -1)
+//
+
+template<class type>
+void Array<type>::zero(int minIndex, int maxIndex) {
+ if (size == 0) return;
+ if (minIndex == -1) minIndex = 0;
+ if (maxIndex == -1) maxIndex = size-1;
+
+ if (minIndex < 0 || maxIndex < 0 || minIndex > maxIndex ||
+ maxIndex >= size) {
+ cerr << "Error in zero function: min = " << minIndex
+ << " max = " << maxIndex << " size = " << size << endl;
+ exit(1);
+ }
+
+ for (int i=minIndex; i<=maxIndex; i++) {
+ array[i] = 0;
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+// operators
+//
+
+
+template<class type>
+int Array<type>::operator==(const Array<type>& aArray) {
+ if (getSize() != aArray.getSize()) {
+ return 0;
+ }
+ Array<type>& t = *this;
+ int i;
+ for (i=0; i<getSize(); i++) {
+ if (t[i] != aArray[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator=
+//
+
+template<class type>
+Array<type>& Array<type>::operator=(const Array<type>& anArray) {
+ if (allocSize < anArray.size) {
+ if (allocSize != 0) {
+ delete [] array;
+ }
+ allocSize = anArray.size;
+ size = anArray.size;
+ array = new type[size];
+ allowGrowthQ = anArray.allowGrowthQ;
+ growthAmount = anArray.growthAmount;
+ maxSize = anArray.maxSize;
+ }
+ size = anArray.size;
+ for (int i=0; i<size; i++) {
+ array[i] = anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator+=
+//
+
+template<class type>
+Array<type>& Array<type>::operator+=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] += anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator+
+//
+
+template<class type>
+Array<type> Array<type>::operator+(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray += anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator+(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] += aNumber;
+ }
+ return anArray;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator-=
+//
+
+template<class type>
+Array<type>& Array<type>::operator-=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] -= anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator-
+//
+
+template<class type>
+Array<type> Array<type>::operator-(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray -= anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator-(void) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] = -anArray[i];
+ }
+ return anArray;
+}
+
+template<class type>
+Array<type> Array<type>::operator-(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] -= aNumber;
+ }
+ return anArray;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator*=
+//
+
+template<class type>
+Array<type>& Array<type>::operator*=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] *= anArray.array[i];
+ }
+
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// Array::operator*
+//
+
+template<class type>
+Array<type> Array<type>::operator*(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray *= anArray;
+ return bArray;
+}
+
+
+template<class type>
+Array<type> Array<type>::operator*(type aNumber) const {
+ Array<type> anArray(*this);
+ for (int i=0; i<size; i++) {
+ anArray[i] *= aNumber;
+ }
+ return anArray;
+}
+
+//////////////////////////////
+//
+// Array::operator/=
+//
+
+template<class type>
+Array<type>& Array<type>::operator/=(const Array<type>& anArray) {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ for (int i=0; i<size; i++) {
+ array[i] /= anArray.array[i];
+ }
+
+ return *this;
+}
+
+//////////////////////////////
+//
+// Array::operator/
+//
+
+template<class type>
+Array<type> Array<type>::operator/(const Array<type>& anArray) const {
+ if (size != anArray.size) {
+ cerr << "Error: different size arrays " << size << " and "
+ << anArray.size << endl;
+ exit(1);
+ }
+
+ Array<type> bArray(*this);
+ bArray /= anArray;
+ return bArray;
+}
+
+
+#endif /* _ARRAY_CPP_INCLUDED */
+
+
+
+// md5sum: 8f52a167c93f51702ce316204fd6e722 - Array.cpp =css= 20030102
diff --git a/src/midiio/include/Array.h b/src/midiio/include/Array.h
new file mode 100644
index 0000000..75e08eb
--- /dev/null
+++ b/src/midiio/include/Array.h
@@ -0,0 +1,67 @@
+//
+// Copyright 1997-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Sun May 11 20:33:13 GMT-0800 1997
+// Last Modified: Wed Jul 7 11:44:50 PDT 1999 (added setAll() function)
+// Last Modified: Mon Jul 29 22:08:32 PDT 2002 (added operator==)
+// Filename: ...sig/maint/code/base/Array/Array.h
+// Web Address: http://sig.sapp.org/include/sigBase/Array.h
+// Documentation: http://sig.sapp.org/doc/classes/Array
+// Syntax: C++
+//
+// Description: An array which can grow dynamically. Array is derived from
+// the Collection class and adds various mathematical operators
+// to the Collection class. The Array template class is used for
+// storing numbers of any type which can be added, multiplied
+// and divided into one another.
+//
+
+#ifndef _ARRAY_H_INCLUDED
+#define _ARRAY_H_INCLUDED
+
+#include "Collection.h"
+
+
+template<class type>
+class Array : public Collection<type> {
+ public:
+ Array (void);
+ Array (int arraySize);
+ Array (Array<type>& aArray);
+ Array (int arraySize, type *anArray);
+ ~Array ();
+
+ void setAll (type aValue);
+ type sum (void);
+ type sum (int lowIndex, int hiIndex);
+ void zero (int minIndex = -1, int maxIndex = -1);
+
+ int operator== (const Array<type>& aArray);
+ Array<type>& operator= (const Array<type>& aArray);
+ Array<type>& operator+= (const Array<type>& aArray);
+ Array<type>& operator-= (const Array<type>& aArray);
+ Array<type>& operator*= (const Array<type>& aArray);
+ Array<type>& operator/= (const Array<type>& aArray);
+
+ Array<type> operator+ (const Array<type>& aArray) const;
+ Array<type> operator+ (type aNumber) const;
+ Array<type> operator- (const Array<type>& aArray) const;
+ Array<type> operator- (void) const;
+
+ Array<type> operator- (type aNumber) const;
+ Array<type> operator* (const Array<type>& aArray) const;
+ Array<type> operator* (type aNumber) const;
+ Array<type> operator/ (const Array<type>& aArray) const;
+};
+
+
+#include "Array.cpp" /* necessary for templates */
+
+
+
+#endif /* _ARRAY_H_INCLUDED */
+
+
+
+// md5sum: 09d1b1f8e70ecde53f484548e48f33c3 - Array.h =css= 20030102
diff --git a/src/midiio/include/CircularBuffer.cpp b/src/midiio/include/CircularBuffer.cpp
new file mode 100644
index 0000000..9f4aca6
--- /dev/null
+++ b/src/midiio/include/CircularBuffer.cpp
@@ -0,0 +1,291 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Wed Jan 21 23:16:54 GMT-0800 1998
+// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/CircularBuffer.cpp
+// Syntax: C++
+//
+// Description: A Circular buffer designed to handle MIDI input,
+// but able to store any type of object. Elements
+// can be read out of the buffer in two ways.
+// (1) from a read pointer which extracts the
+// elements in order by following the write pointer,
+// and (2) from an index operator related to the
+// write pointer's location, for example,
+// object[0] is the last value written into the
+// buffer and object[-1] (or object[1]) is the
+// item written just before that.
+//
+//
+
+#ifndef _CIRCULARBUFFER_CPP_INCLUDED
+#define _CIRCULARBUFFER_CPP_INCLUDED
+
+#include "CircularBuffer.h"
+#include <stdlib.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// CircularBuffer::CircularBuffer -- Constructor.
+//
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(void) {
+ size = 0;
+ buffer = NULL;
+ reset();
+}
+
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(int maxElements) {
+ if (maxElements < 0) {
+ std::cerr << "Error: cannot have a negative number of elements: "
+ << maxElements << std::endl;
+ exit(1);
+ }
+ if (maxElements == 0) {
+ size = 0;
+ buffer = NULL;
+ reset();
+ } else {
+ size = maxElements;
+ buffer = new type[maxElements];
+ reset();
+ }
+}
+
+
+template<class type>
+CircularBuffer<type>::CircularBuffer(const CircularBuffer<type>& anotherBuffer) {
+ size = anotherBuffer.size;
+ if (getSize() == 0) {
+ buffer = NULL;
+ reset();
+ } else {
+ buffer = new type[getSize()];
+ writeIndex = anotherBuffer.writeIndex;
+ readIndex = anotherBuffer.readIndex;
+ itemCount = anotherBuffer.itemCount;
+ for (int i=0; i<getSize(); i++) {
+ buffer[i] = anotherBuffer.buffer[i];
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::~CircularBuffer -- Destructor.
+// deallocates buffer memory.
+//
+
+template<class type>
+CircularBuffer<type>::~CircularBuffer() {
+ if (buffer != NULL) {
+ delete [] buffer;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::capacity -- returns the number of items which
+// can be added to the buffer. Returns a positive number
+// if the buffer has empty locations available. Returns 0 if the
+// buffer is 100% full. Returns a negative number if the
+// buffer has overflowed.
+
+template<class type>
+int CircularBuffer<type>::capacity(void) const {
+ return getSize() - getCount();
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::extract -- reads the next value from the buffer.
+//
+
+template<class type>
+type CircularBuffer<type>::extract(void) {
+ itemCount--;
+ if (itemCount < 0) {
+ std::cerr << "Error: no elements in buffer to extract." << std::endl;
+ exit(1);
+ }
+ increment(readIndex);
+ return buffer[readIndex];
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::getCount -- returns the number of elements
+// between the write index and the read index.
+//
+
+template<class type>
+int CircularBuffer<type>::getCount(void) const {
+ return itemCount;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::getSize -- returns the allocated size of the buffer.
+//
+
+template<class type>
+int CircularBuffer<type>::getSize(void) const {
+ return size;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::insert -- add an element to the circular buffer
+//
+
+template<class type>
+void CircularBuffer<type>::insert(const type& anItem) {
+ itemCount++;
+ increment(writeIndex);
+ buffer[writeIndex] = anItem;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::operator[] -- access an element relative to the
+// currently written element
+//
+
+template<class type>
+type& CircularBuffer<type>::operator[](int index) {
+ if (buffer == NULL) {
+ std::cerr << "Error: buffer has no allocated space" << std::endl;
+ exit(1);
+ }
+ int realIndex = (index < 0) ? -index : index;
+ if (realIndex >= getSize()) {
+ std::cerr << "Error: Invalid access: " << realIndex << ", maximum is "
+ << getSize()-1 << std::endl;
+ exit(1);
+ }
+ realIndex = writeIndex - realIndex;
+
+ // should need to go through this loop a max of one time:
+ while (realIndex < 0) {
+ realIndex += getSize();
+ }
+
+ return buffer[realIndex];
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::read -- an alias for the extract function.
+//
+
+template<class type>
+type CircularBuffer<type>::read(void) {
+ return extract();
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::reset -- throws out all previous data and
+// sets the read/write/count to initial values. The size
+// data variable must be valid before this function is
+// called.
+//
+
+template<class type>
+void CircularBuffer<type>::reset(void) {
+ readIndex = writeIndex = getSize() - 1;
+ itemCount = 0;
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::setSize -- warning: will throw out all previous data
+// stored in buffer.
+//
+
+template<class type>
+void CircularBuffer<type>::setSize(int aSize) {
+ if (aSize < 0) {
+ std::cerr << "Error: cannot have a negative buffer size: " << aSize << std::endl;
+ exit(1);
+ }
+ if (buffer != NULL) {
+ delete [] buffer;
+ }
+
+ if (aSize == 0) {
+ size = aSize;
+ buffer = NULL;
+ reset();
+ } else {
+ size = aSize;
+ buffer = new type[aSize];
+ reset();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// CircularBuffer::write -- an alias for the insert function.
+//
+
+template<class type>
+void CircularBuffer<type>::write(const type& anElement) {
+ write(anElement);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// CircularBuffer::increment -- adds one to specified index and
+// will automatically wrap the index when it gets too large.
+//
+
+template<class type>
+void CircularBuffer<type>::increment(int& index) {
+ index++;
+ if (index >= getSize()) {
+ index = 0;
+ }
+}
+
+
+#endif /* _CIRCULARBUFFER_CPP_INCLUDED */
+
+
+
+// md5sum: 31b2e8d6efe7398a12ddb0a1b5680ca2 - CircularBuffer.cpp =css= 20030102
diff --git a/src/midiio/include/CircularBuffer.h b/src/midiio/include/CircularBuffer.h
new file mode 100644
index 0000000..6bb3071
--- /dev/null
+++ b/src/midiio/include/CircularBuffer.h
@@ -0,0 +1,66 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Wed Jan 21 23:08:13 GMT-0800 1998
+// Filename: ...sig/maint/code/base/CircularBuffer/CircularBuffer.h
+// Web Address: http://sig.sapp.org/include/sigBase/CircularBuffer.cpp
+// Documentation: http://sig.sapp.org/doc/classes/CircularBuffer
+// Syntax: C++
+//
+// Description: A Circular buffer designed to handle MIDI input,
+// but able to store any type of object. Elements
+// can be read out of the buffer in two ways.
+// (1) from a read pointer which extracts the
+// elements in order by following the write pointer,
+// and (2) from an index operator related to the
+// write pointer's location, for example,
+// object[0] is the last value written into the
+// buffer and object[-1] (or object[1]) is the
+// item written just before that.
+//
+
+#ifndef _CIRCULARBUFFER_H_INCLUDED
+#define _CIRCULARBUFFER_H_INCLUDED
+
+
+template<class type>
+class CircularBuffer {
+ public:
+ CircularBuffer (void);
+ CircularBuffer (int maxElements);
+ CircularBuffer (const CircularBuffer<type>&
+ anotherBuffer);
+ ~CircularBuffer ();
+
+ int capacity (void) const;
+ type extract (void);
+ int getCount (void) const;
+ int getSize (void) const;
+ void insert (const type& aMessage);
+ type& operator[] (int index);
+ type read (void);
+ void reset (void);
+ void setSize (int aSize);
+ void write (const type& aMessage);
+
+ protected:
+ type* buffer;
+ int size;
+ int writeIndex;
+ int readIndex;
+ int itemCount;
+
+ void increment (int& index);
+};
+
+
+#include "CircularBuffer.cpp"
+
+
+
+#endif /* _CIRCULARBUFFER_H_INCLUDED */
+
+
+
+// md5sum: 2857693ec37fdcb6df09db479faf110b - CircularBuffer.h =css= 20030102
diff --git a/src/midiio/include/Collection.cpp b/src/midiio/include/Collection.cpp
new file mode 100644
index 0000000..74eef16
--- /dev/null
+++ b/src/midiio/include/Collection.cpp
@@ -0,0 +1,355 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Wed Apr 23 22:08:34 GMT-0800 1997
+// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function)
+// Filename: ...sig/maint/code/base/Collection/Collection.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Collection.cpp
+// Syntax: C++
+//
+// Description: A dynamic array which can grow as necessary.
+// This class can hold any type of item, but the
+// derived Array class is specifically for collections
+// of numbers.
+//
+
+#ifndef _COLLECTION_CPP_INCLUDED
+#define _COLLECTION_CPP_INCLUDED
+
+#include "Collection.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+//////////////////////////////
+//
+// Collection::Collection
+//
+
+template<class type>
+Collection<type>::Collection(void) {
+ allocSize = 0;
+ size = 0;
+ array = NULL;
+ allowGrowthQ = 0;
+ growthAmount = 8;
+ maxSize = 0;
+}
+
+template<class type>
+Collection<type>::Collection(int arraySize) {
+ array = new type[arraySize];
+ size = arraySize;
+ allocSize = arraySize;
+ allowGrowthQ = 0;
+ growthAmount = arraySize;
+ maxSize = 0;
+}
+
+
+template<class type>
+Collection<type>::Collection(int arraySize, type *aCollection) {
+ size = arraySize;
+ allocSize = arraySize;
+ array = new type[size];
+ for (int i=0; i<size; i++) {
+ array[i] = aCollection[i];
+ }
+ growthAmount = arraySize;
+ allowGrowthQ = 0;
+ maxSize = 0;
+}
+
+
+template<class type>
+Collection<type>::Collection(Collection<type>& aCollection) {
+ size = aCollection.size;
+ allocSize = size;
+ array = new type[size];
+ for (int i=0; i<size; i++) {
+ array[i] = aCollection.array[i];
+ }
+ allowGrowthQ = aCollection.allowGrowthQ;
+ growthAmount = aCollection.growthAmount;
+ maxSize = aCollection.maxSize;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::~Collection
+//
+
+template<class type>
+Collection<type>::~Collection() {
+ if (getAllocSize() != 0) {
+ delete [] array;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::allowGrowth
+// default value: status = 1
+//
+
+template<class type>
+void Collection<type>::allowGrowth(int status) {
+ if (status == 0) {
+ allowGrowthQ = 0;
+ } else {
+ allowGrowthQ = 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::append
+//
+
+template<class type>
+void Collection<type>::append(type& element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = element;
+ size++;
+}
+
+template<class type>
+void Collection<type>::appendcopy(type element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = element;
+ size++;
+}
+
+template<class type>
+void Collection<type>::append(type *element) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ array[size] = *element;
+ size++;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::grow
+// default parameter: growamt = -1
+//
+
+template<class type>
+void Collection<type>::grow(long growamt) {
+ allocSize += growamt > 0 ? growamt : growthAmount;
+ if (maxSize != 0 && getAllocSize() > maxSize) {
+ std::cerr << "Error: Maximum size allowed for array exceeded." << std::endl;
+ exit(1);
+ }
+
+ type *temp = new type[getAllocSize()];
+ for (int i=0; i<size; i++) {
+ temp[i] = array[i];
+ }
+ array = temp;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::pointer
+//
+
+template<class type>
+type* Collection<type>::pointer(void) {
+ return array;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getBase
+//
+
+template<class type>
+type* Collection<type>::getBase(void) {
+ return array;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getAllocSize
+//
+
+template<class type>
+long Collection<type>::getAllocSize(void) const {
+ return allocSize;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::getSize --
+//
+
+template<class type>
+long Collection<type>::getSize(void) const {
+ return size;
+}
+
+
+
+//////////////////////////////
+//
+// Collection::last --
+//
+
+template<class type>
+type& Collection<type>::last(void) {
+ return array[getSize()-1];
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setAllocSize
+//
+
+template<class type>
+void Collection<type>::setAllocSize(long aSize) {
+ if (aSize < getSize()) {
+ std::cerr << "Error: cannot set allocated size smaller than actual size."
+ << std::endl;
+ exit(1);
+ }
+
+ if (aSize <= getAllocSize()) {
+ shrinkTo(aSize);
+ } else {
+ grow(aSize-getAllocSize());
+ size = aSize;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setGrowth
+// default parameter: growth = -1
+//
+
+template<class type>
+void Collection<type>::setGrowth(long growth) {
+ if (growth > 0) {
+ growthAmount = growth;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Collection::setSize
+//
+
+template<class type>
+void Collection<type>::setSize(long newSize) {
+ if (newSize <= getAllocSize()) {
+ size = newSize;
+ } else {
+ grow(newSize-getAllocSize());
+ size = newSize;
+ }
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Collection operators
+//
+
+//////////////////////////////
+//
+// Collection::operator[]
+//
+
+template<class type>
+type& Collection<type>::operator[](int elementIndex) {
+ if (allowGrowthQ && elementIndex == size) {
+ if (size == getAllocSize()) {
+ grow();
+ }
+ size++;
+ } else if (elementIndex >= size) {
+ std::cerr << "Error: accessing invalid array location "
+ << elementIndex
+ << " Maximum is " << size-1 << std::endl;
+ exit(1);
+ }
+ return array[elementIndex];
+}
+
+
+//////////////////////////////
+//
+// Collection::operator[] const
+//
+
+template<class type>
+type Collection<type>::operator[](int elementIndex) const {
+ if (elementIndex >= size) {
+ std::cerr << "Error: accessing invalid array location "
+ << elementIndex
+ << " Maximum is " << size-1 << std::endl;
+ exit(1);
+ }
+ return array[elementIndex];
+}
+
+//////////////////////////////
+//
+// shrinkTo
+//
+
+template<class type>
+void Collection<type>::shrinkTo(long aSize) {
+ if (aSize < getSize()) {
+ exit(1);
+ }
+
+ type *temp = new type[aSize];
+ for (int i=0; i<size; i++) {
+ temp[i] = array[i];
+ }
+ delete [] array;
+ array = temp;
+
+ allocSize = aSize;
+ if (size > allocSize) {
+ size = allocSize;
+ }
+}
+
+
+#endif /* _COLLECTION_CPP_INCLUDED */
+
+
+
+// md5sum: 9929fee30b1bede4305e1fb46303ddc1 - Collection.cpp =css= 20030102
diff --git a/src/midiio/include/Collection.h b/src/midiio/include/Collection.h
new file mode 100644
index 0000000..6775366
--- /dev/null
+++ b/src/midiio/include/Collection.h
@@ -0,0 +1,70 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Feb 5 19:42:53 PST 1997
+// Last Modified: Tue Apr 22 20:28:16 GMT-0800 1997
+// Last Modified: Fri Sep 14 15:50:52 PDT 2001 (added last() function)
+// Filename: ...sig/maint/code/base/Collection/Collection.h
+// Web Address: http://sig.sapp.org/include/sigBase/Collection.h
+// Documentation: http://sig.sapp.org/doc/classes/Collection
+// Syntax: C++
+//
+// Description: A dynamic array which can grow as necessary.
+// This class can hold any type of item, but the
+// derived Array class is specifically for collections
+// of numbers.
+//
+
+#ifndef _COLLECTION_H_INCLUDED
+#define _COLLECTION_H_INCLUDED
+
+
+template<class type>
+class Collection {
+ public:
+ Collection (void);
+ Collection (int arraySize);
+ Collection (int arraySize, type *aCollection);
+ Collection (Collection<type>& aCollection);
+ ~Collection ();
+
+ void allowGrowth (int status = 1);
+ void append (type& element);
+ void appendcopy (type element);
+ void append (type* element);
+ type *getBase (void);
+ long getAllocSize (void) const;
+ long getSize (void) const;
+ type *pointer (void);
+ void setAllocSize (long aSize);
+ void setGrowth (long growth);
+ void setSize (long newSize);
+ type& operator[] (int arrayIndex);
+ type operator[] (int arrayIndex) const;
+ void grow (long growamt = -1);
+ type& last (void);
+
+
+ protected:
+ long size; // actual array size
+ long allocSize; // maximum allowable array size
+ type *array; // where the array data is stored
+ char allowGrowthQ; // allow/disallow growth
+ long growthAmount; // number of elements to grow by if index
+ // element one beyond max size is accessed
+ long maxSize; // the largest size the array is allowed
+ // to grow to, if 0, then ignore max
+
+ void shrinkTo (long aSize);
+};
+
+
+#include "Collection.cpp"
+
+
+
+#endif /* _COLLECTION_H_INCLUDED */
+
+
+
+// md5sum: 01bec04835c0bd117f40c2bfe51c4abd - Collection.h =css= 20030102
diff --git a/src/midiio/include/FileIO.h b/src/midiio/include/FileIO.h
new file mode 100644
index 0000000..fdec5de
--- /dev/null
+++ b/src/midiio/include/FileIO.h
@@ -0,0 +1,148 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri May 9 22:30:32 PDT 1997
+// Last Modified: Sun Dec 14 05:26:16 GMT-0800 1997
+// Filename: ...sig/maint/code/base/FileIO/FileIO.h
+// Web Address: http://sig.sapp.org/include/sigBase/FileIO.h
+// Documentation: http://sig.sapp.org/doc/classes/FileIO
+// Syntax: C++
+//
+// Description: Derived from the fstream class, this class has
+// functions which allow writing binary files in
+// both little and big endian formats. Useful for
+// writing files such as soundfiles and MIDI files
+// which require numbers to be stored in a particular
+// endian format.
+//
+
+#ifndef _FILEIO_H_INCLUDED
+#define _FILEIO_H_INCLUDED
+
+
+#include <fstream>
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+// templates would be nice to use here, but they don't seem
+// to work intuitively...
+
+class FileIO : public std::fstream {
+ public:
+ FileIO (void);
+ FileIO (const char* filename, std::ios::openmode state);
+ ~FileIO ();
+
+ void readBigEndian (char& aNumber);
+ void readBigEndian (uchar& aNumber);
+ void readBigEndian (short& aNumber);
+ void readBigEndian (ushort& aNumber);
+ void readBigEndian (long& aNumber);
+ void readBigEndian (ulong& aNumber);
+ void readBigEndian (int& aNumber);
+ void readBigEndian (uint& aNumber);
+ void readBigEndian (float& aNumber);
+ void readBigEndian (double& aNumber);
+
+ void readLittleEndian (char& aNumber);
+ void readLittleEndian (uchar& aNumber);
+ void readLittleEndian (short& aNumber);
+ void readLittleEndian (ushort& aNumber);
+ void readLittleEndian (long& aNumber);
+ void readLittleEndian (ulong& aNumber);
+ void readLittleEndian (int& aNumber);
+ void readLittleEndian (uint& aNumber);
+ void readLittleEndian (float& aNumber);
+ void readLittleEndian (double& aNumber);
+
+ void readMachineEndian (char& aNumber);
+ void readMachineEndian (uchar& aNumber);
+ void readMachineEndian (short& aNumber);
+ void readMachineEndian (ushort& aNumber);
+ void readMachineEndian (long& aNumber);
+ void readMachineEndian (ulong& aNumber);
+ void readMachineEndian (int& aNumber);
+ void readMachineEndian (uint& aNumber);
+ void readMachineEndian (float& aNumber);
+ void readMachineEndian (double& aNumber);
+
+ void readNotMachineEndian (char& aNumber);
+ void readNotMachineEndian (uchar& aNumber);
+ void readNotMachineEndian (short& aNumber);
+ void readNotMachineEndian (ushort& aNumber);
+ void readNotMachineEndian (long& aNumber);
+ void readNotMachineEndian (ulong& aNumber);
+ void readNotMachineEndian (int& aNumber);
+ void readNotMachineEndian (uint& aNumber);
+ void readNotMachineEndian (float& aNumber);
+ void readNotMachineEndian (double& aNumber);
+
+ void writeBigEndian (char aNumber);
+ void writeBigEndian (uchar aNumber);
+ void writeBigEndian (short aNumber);
+ void writeBigEndian (ushort aNumber);
+ void writeBigEndian (long aNumber);
+ void writeBigEndian (ulong aNumber);
+ void writeBigEndian (int aNumber);
+ void writeBigEndian (uint aNumber);
+ void writeBigEndian (float aNumber);
+ void writeBigEndian (double aNumber);
+
+ void writeLittleEndian (char aNumber);
+ void writeLittleEndian (uchar aNumber);
+ void writeLittleEndian (short aNumber);
+ void writeLittleEndian (ushort aNumber);
+ void writeLittleEndian (long aNumber);
+ void writeLittleEndian (ulong aNumber);
+ void writeLittleEndian (int aNumber);
+ void writeLittleEndian (uint aNumber);
+ void writeLittleEndian (float aNumber);
+ void writeLittleEndian (double aNumber);
+
+ void writeMachineEndian (char aNumber);
+ void writeMachineEndian (uchar aNumber);
+ void writeMachineEndian (short aNumber);
+ void writeMachineEndian (ushort aNumber);
+ void writeMachineEndian (long aNumber);
+ void writeMachineEndian (ulong aNumber);
+ void writeMachineEndian (int aNumber);
+ void writeMachineEndian (uint aNumber);
+ void writeMachineEndian (float aNumber);
+ void writeMachineEndian (double aNumber);
+
+ void writeNotMachineEndian (char aNumber);
+ void writeNotMachineEndian (uchar aNumber);
+ void writeNotMachineEndian (short aNumber);
+ void writeNotMachineEndian (ushort aNumber);
+ void writeNotMachineEndian (long aNumber);
+ void writeNotMachineEndian (ulong aNumber);
+ void writeNotMachineEndian (int aNumber);
+ void writeNotMachineEndian (uint aNumber);
+ void writeNotMachineEndian (float aNumber);
+ void writeNotMachineEndian (double aNumber);
+
+ protected:
+
+ char flipBytes (char aNumber);
+ uchar flipBytes (uchar aNumber);
+ short flipBytes (short aNumber);
+ ushort flipBytes (ushort aNumber);
+ long flipBytes (long aNumber);
+ ulong flipBytes (ulong aNumber);
+ int flipBytes (int aNumber);
+ uint flipBytes (uint aNumber);
+ float flipBytes (float aNumber);
+ double flipBytes (double aNumber);
+
+};
+
+
+
+#endif /* _FILEIO_H_INCLUDED */
+
+
+
+// md5sum: 0a146ebe5c6bd0850be973f612827d20 - FileIO.h =css= 20030102
diff --git a/src/midiio/include/MidiFile.h b/src/midiio/include/MidiFile.h
new file mode 100644
index 0000000..10794d5
--- /dev/null
+++ b/src/midiio/include/MidiFile.h
@@ -0,0 +1,108 @@
+//
+// Copyright 1999-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Nov 26 14:12:01 PST 1999
+// Last Modified: Fri Dec 2 13:26:44 PST 1999
+// Last Modified: Fri Nov 10 12:13:15 PST 2000 (added some more editing cap.)
+// Last Modified: Thu Jan 10 10:03:39 PST 2002 (added allocateEvents())
+// Last Modified: Mon Jun 10 22:43:10 PDT 2002 (added clear())
+// Filename: ...sig/include/sigInfo/MidiFile.h
+// Web Address: http://sig.sapp.org/include/sigInfo/MidiFile.h
+// Syntax: C++
+//
+// Description: A class which can read/write Standard MIDI files.
+// MIDI data is stored by track in an array. This
+// class is used for example in the MidiPerform class.
+//
+
+#ifndef _MIDIfILE_H_INCLUDED
+#define _MIDIfILE_H_INCLUDED
+
+#include "FileIO.h"
+#include "Array.h"
+#include "Collection.h"
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+
+#define TIME_STATE_DELTA 0
+#define TIME_STATE_ABSOLUTE 1
+
+#define TRACK_STATE_SPLIT 0
+#define TRACK_STATE_JOINED 1
+
+
+class _MFEvent {
+ public:
+ _MFEvent (void);
+ _MFEvent (int command);
+ _MFEvent (int command, int param1);
+ _MFEvent (int command, int param1, int param2);
+ _MFEvent (int track, int command, int param1, int param2);
+ _MFEvent (int aTime, int aTrack, int command, int param1, int param2);
+ ~_MFEvent ();
+ int time;
+ int track;
+ Array<uchar> data;
+};
+
+
+
+class MidiFile {
+ public:
+ MidiFile (void);
+ MidiFile (char* aFile);
+ ~MidiFile ();
+
+ void absoluteTime (void);
+ int addEvent (int aTrack, int aTime,
+ Array<uchar>& midiData);
+ int addTrack (void);
+ int addTrack (int count);
+ void allocateEvents (int track, int aSize);
+ void deltaTime (void);
+ void deleteTrack (int aTrack);
+ void erase (void);
+ void clear (void);
+ _MFEvent& getEvent (int aTrack, int anIndex);
+ int getTimeState (void);
+ int getTrackState (void);
+ int getTicksPerQuarterNote (void);
+ int getTrackCount (void);
+ int getNumTracks (void);
+ int getNumEvents (int aTrack);
+ void joinTracks (void);
+ void mergeTracks (int aTrack1, int aTrack2);
+ int read (char* aFile);
+ void setTicksPerQuarterNote (int ticks);
+ void sortTrack (Collection<_MFEvent>& trackData);
+ void sortTracks (void);
+ void splitTracks (void);
+ int write (const char* aFile);
+
+ protected:
+ Collection<Collection<_MFEvent>*> events; // midi file events
+ int ticksPerQuarterNote; // time base of file
+ int trackCount; // # of tracks in file
+ int theTrackState; // joined or split
+ int theTimeState; // absolute or delta
+ char* readFileName; // read file name
+
+ private:
+ void extractMidiData (FileIO& inputfile, Array<uchar>& array,
+ uchar& runningCommand);
+ ulong extractVlvTime (FileIO& inputfile);
+ ulong unpackVLV (uchar a, uchar b, uchar c, uchar d, uchar e);
+ void writeVLValue (long aValue, Array<uchar>& data);
+};
+
+
+int eventcompare(const void* a, const void* b);
+std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile);
+
+#endif /* _MIDIfILE_H_INCLUDED */
+
+
+
+// md5sum: ff46e64698e2d9e88ebeef3efa9927d0 - MidiFile.h =css= 20030102
diff --git a/src/midiio/include/MidiFileWrite.h b/src/midiio/include/MidiFileWrite.h
new file mode 100644
index 0000000..a213fdf
--- /dev/null
+++ b/src/midiio/include/MidiFileWrite.h
@@ -0,0 +1,61 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998
+// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998
+// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiFileWrite.h
+// Syntax: C++
+//
+// Description: The MidiFileWrite class will write out a Type 0 MidiFile.
+// Used for recording MIDI data streams into Standard
+// MIDI files.
+//
+
+#ifndef _MIDIFILEWRITE_INCLUDED
+#define _MIDIFILEWRITE_INCLUDED
+
+
+#include "FileIO.h"
+
+
+class MidiFileWrite {
+ public:
+ MidiFileWrite (void);
+ MidiFileWrite (const char* aFilename, int startTime = -1);
+ ~MidiFileWrite ();
+
+ void close (void);
+ void setup (const char* aFilename, int startTime = -1);
+ void start (int startTime = -1);
+ void writeAbsolute (int aTime, int command, int p1, int p2);
+ void writeAbsolute (int aTime, int command, int p1);
+ void writeAbsolute (int aTime, int command);
+ void writeRaw (uchar aByte);
+ void writeRaw (uchar aByte, uchar Byte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte,
+ uchar dByte);
+ void writeRaw (uchar aByte, uchar Byte, uchar cByte,
+ uchar dByte, uchar eByte);
+ void writeRaw (uchar* anArray, int arraySize);
+ void writeRelative (int aTime, int command, int p1, int p2);
+ void writeRelative (int aTime, int command, int p1);
+ void writeRelative (int aTime, int command);
+ void writeVLValue (long aValue);
+
+
+ protected:
+ FileIO *midifile; // file stream for MIDI file
+ long trackSize; // size count for MIDI track
+ int lastPlayTime; // for calculating delta times
+ int openQ; // for checking file status
+
+};
+
+
+
+#endif /* _MIDIFILEWRITE_INCLUDED */
+
+
+
+// md5sum: 44ac572078bff648d096c7e7867d1b3c - MidiFileWrite.h =css= 20030102
diff --git a/src/midiio/include/MidiIO.h b/src/midiio/include/MidiIO.h
new file mode 100644
index 0000000..80c9168
--- /dev/null
+++ b/src/midiio/include/MidiIO.h
@@ -0,0 +1,58 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Sun Jan 25 15:44:35 GMT-0800 1998
+// Filename: ...sig/code/control/MidiIO/MidiIO.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiIO.h
+// Syntax: C++
+//
+// Description: A unified class for MidiInput and MidiOutput that handles
+// MIDI input and output connections. The Synthesizer
+// and RadioBaton classes are derived from this class.
+//
+
+#ifndef _MIDIIO_H_INCLUDED
+#define _MIDIIO_H_INCLUDED
+
+
+#include "MidiInput.h"
+#include "MidiOutput.h"
+
+
+class MidiIO : public MidiOutput, public MidiInput {
+ public:
+ MidiIO (void);
+ MidiIO (int outPort, int inPort);
+ ~MidiIO ();
+
+ void close (void);
+ void closeInput (void);
+ void closeOutput (void);
+ int getChannelInOffset (void) const;
+ int getChannelOutOffset (void) const;
+ int getInputPort (void);
+ int getInputTrace (void);
+ int getNumInputPorts (void);
+ int getNumOutputPorts (void);
+ int getOutputPort (void);
+ int getOutputTrace (void);
+ int open (void);
+ int openInput (void);
+ int openOutput (void);
+ void setChannelOffset (int anOffset);
+ void setInputPort (int aPort);
+ void setInputTrace (int aState);
+ void setOutputPort (int aPort);
+ void setOutputTrace (int aState);
+ void toggleInputTrace (void);
+ void toggleOutputTrace (void);
+
+};
+
+
+
+#endif /* _MIDIIO_H_INCLUDED */
+
+
+
+// md5sum: 9f6122405c4d9e83994457210217ff22 - MidiIO.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort.h b/src/midiio/include/MidiInPort.h
new file mode 100644
index 0000000..ac225c4
--- /dev/null
+++ b/src/midiio/include/MidiInPort.h
@@ -0,0 +1,98 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:35:31 GMT-0800 1998
+// Last Modified: Thu Jan 22 23:13:54 GMT-0800 1998
+// Last Modified: Sat Nov 7 16:09:18 PST 1998
+// Last Modified: Tue Jun 29 16:14:50 PDT 1999 (added Sysex input)
+// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifndef _MIDIINPORT_H_INCLUDED
+#define _MIDIINPORT_H_INCLUDED
+
+
+#include "MidiMessage.h"
+
+#ifdef VISUAL
+ #define MIDIINPORT MidiInPort_visual
+ #include "MidiInPort_visual.h"
+#elif defined(LINUX) && defined(ALSA) && defined(OSS)
+ #define MIDIINPORT MidiInPort_linux
+ #include "MidiInPort_linux.h"
+#elif defined(LINUX) && defined(ALSA) && !defined(OSS)
+ #define MIDIINPORT MidiInPort_alsa
+ #include "MidiInPort_alsa.h"
+#elif defined (LINUX) && defined(OSS) && !defined(ALSA)
+ #define MIDIINPORT MidiInPort_oss
+ #include "MidiInPort_oss.h"
+#elif defined(LINUX)
+ #define MIDIINPORT MidiInPort_oss
+ #include "MidiInPort_oss.h"
+#else
+ #define MIDIINPORT MidiInPort_unsupported
+ #include "MidiInPort_unsupported.h"
+#endif
+
+
+class MidiInPort : protected MIDIINPORT {
+ public:
+ MidiInPort (void) : MIDIINPORT() {}
+ MidiInPort (int aPort, int autoOpen = 1) :
+ MIDIINPORT(aPort, autoOpen) {}
+ ~MidiInPort() { }
+
+ void clearSysex(void) { MIDIINPORT::clearSysex(); }
+ void clearSysex(int buffer) { MIDIINPORT::clearSysex(buffer); }
+ void close(void) { MIDIINPORT::close(); }
+ void closeAll(void) { MIDIINPORT::closeAll(); }
+ MidiMessage extract(void) { return MIDIINPORT::extract(); }
+ int getBufferSize(void) { return MIDIINPORT::getBufferSize(); }
+ int getChannelOffset(void) const {
+ return MIDIINPORT::getChannelOffset(); }
+ int getCount(void) { return MIDIINPORT::getCount(); }
+ const char* getName(void) { return MIDIINPORT::getName(); }
+ static const char* getName(int i) { return MIDIINPORT::getName(i); }
+ static int getNumPorts(void) {
+ return MIDIINPORT::getNumPorts(); }
+ int getPort(void) { return MIDIINPORT::getPort(); }
+ int getPortStatus(void){
+ return MIDIINPORT::getPortStatus(); }
+ uchar* getSysex(int buffer) { return MIDIINPORT::getSysex(buffer); }
+ int getSysexSize(int buffer) { return MIDIINPORT::getSysexSize(buffer); }
+ int getTrace(void) { return MIDIINPORT::getTrace(); }
+ void insert(const MidiMessage& aMessage) {
+ MIDIINPORT::insert(aMessage); }
+ int installSysex(uchar* anArray, int aSize) {
+ return MIDIINPORT::installSysex(anArray, aSize); }
+ int open(void) { return MIDIINPORT::open(); }
+ MidiMessage& operator[](int index) {
+ return MIDIINPORT::message(index); }
+ void pause(void) { MIDIINPORT::pause(); }
+ void setBufferSize(int aSize) {
+ MIDIINPORT::setBufferSize(aSize); }
+ void setChannelOffset(int anOffset) {
+ MIDIINPORT::setChannelOffset(anOffset); }
+ void setAndOpenPort(int aPort) { setPort(aPort); open(); }
+ void setPort(int aPort) { MIDIINPORT::setPort(aPort); }
+ int setTrace(int aState) {
+ return MIDIINPORT::setTrace(aState); }
+ void toggleTrace(void) { MIDIINPORT::toggleTrace(); }
+ void unpause(void) { MIDIINPORT::unpause(); }
+};
+
+
+
+#endif /* _MIDIINPORT_H_INCLUDED */
+
+
+
+// md5sum: 96f8a2b4411a356d1b73cd96421b8931 - MidiInPort.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_alsa.h b/src/midiio/include/MidiInPort_alsa.h
new file mode 100644
index 0000000..b321600
--- /dev/null
+++ b/src/midiio/include/MidiInPort_alsa.h
@@ -0,0 +1,107 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:05:27 PDT 2000
+// Last Modified: Sat Oct 13 16:11:24 PDT 2001 (updated for ALSA 0.9)
+// Last Modified: Sat Nov 2 20:35:50 PST 2002 (added #ifdef ALSA)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_ALSA_H_INCLUDED
+#define _MIDIINPORT_ALSA_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_alsa.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_alsa : public Sequencer_alsa {
+ public:
+ MidiInPort_alsa (void);
+ MidiInPort_alsa (int aPort, int autoOpen = 1);
+ ~MidiInPort_alsa ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static Array<int> threadinitport;
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static std::ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static Array<pthread_t> midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA(void * x);
+
+};
+
+
+#endif /* ALSA */
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_ALSA_H_INCLUDED */
+
+
+
+// md5sum: 260a0accd6b08b638a00904c382293bc - MidiInPort_alsa.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_alsa05.h b/src/midiio/include/MidiInPort_alsa05.h
new file mode 100644
index 0000000..27af569
--- /dev/null
+++ b/src/midiio/include/MidiInPort_alsa05.h
@@ -0,0 +1,107 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:05:27 PDT 2000
+// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5)
+// Last Modified: Thu Jan 2 18:55:12 PST 2003 (added #ifdef ALSA05)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_alsa05.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_alsa05.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_ALSA05_H_INCLUDED
+#define _MIDIINPORT_ALSA05_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA05
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_alsa05.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_alsa05 : public Sequencer_alsa05 {
+ public:
+ MidiInPort_alsa05 (void);
+ MidiInPort_alsa05 (int aPort, int autoOpen = 1);
+ ~MidiInPort_alsa05 ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static Array<int> threadinitport;
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static Array<pthread_t> midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA05(void * x);
+
+};
+
+
+#endif /* ALSA05 */
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_ALSA05_H_INCLUDED */
+
+
+
+// md5sum: 7b85b4a658c6f1d45dc1da7752f25cae - MidiInPort_alsa05.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_linux.h b/src/midiio/include/MidiInPort_linux.h
new file mode 100644
index 0000000..589d27a
--- /dev/null
+++ b/src/midiio/include/MidiInPort_linux.h
@@ -0,0 +1,94 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:30:04 PDT 2000
+// Last Modified: Thu May 18 23:36:07 PDT 2000 (added ifdef LINUX lines)
+// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifndef _MIDIINPORT_LINUX_H_INCLUDED
+#define _MIDIINPORT_LINUX_H_INCLUDED
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#define MIDI_IN_UNKNOWN_SELECT 0
+#define MIDI_IN_OSS_SELECT 1
+#define MIDI_IN_ALSA_SELECT 2
+
+#include "MidiInPort_oss.h"
+#include "MidiInPort_alsa.h"
+#include "MidiInPort_unsupported.h"
+#include "MidiMessage.h"
+
+
+class MidiInPort_linux {
+ public:
+ MidiInPort_linux(void);
+ MidiInPort_linux(int aPort, int autoOpen = 1);
+ ~MidiInPort_linux();
+
+ void clearSysex (void);
+ void clearSysex (int buffer);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ MidiMessage& operator[] (int index);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setAndOpenPort (int aPort);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ static int getSelect (void);
+ static int selectOSS (void);
+ static int selectALSA (void);
+ static int selectUnknown (void);
+
+ private:
+
+ static int current; // the type of MIDI out selected
+ static int alsaQ; // boolean for if ALSA is present
+ static int ossQ; // boolean for if OSS is present
+ static int objectCount; // keeps track of static variables
+
+ static MidiInPort_oss *oss_input;
+ static MidiInPort_alsa *alsa_input;
+ static MidiInPort_unsupported *unknown_input;
+
+ void determineDrivers (void);
+};
+
+#endif /* ALSA and OSS def */
+#endif /* LINUX def */
+
+#endif /* _MIDIINPORT_LINUX_H_INCLUDED */
+
+
+// md5sum: cc3608fb63ccf222f018efc89a4275f0 - MidiInPort_linux.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_oss.h b/src/midiio/include/MidiInPort_oss.h
new file mode 100644
index 0000000..ffa5666
--- /dev/null
+++ b/src/midiio/include/MidiInPort_oss.h
@@ -0,0 +1,105 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Jan 8 08:33:57 PST 1999
+// Last Modified: Fri Jan 8 08:34:01 PST 1999
+// Last Modified: Tue Jun 29 16:18:02 PDT 1999 (added sysex capability)
+// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiInPort/linux/MidiInPort_oss.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_oss.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux OSS sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPORT_OSS_H_INCLUDED
+#define _MIDIINPORT_OSS_H_INCLUDED
+
+#ifdef LINUX
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+#include "Sequencer_oss.h"
+#include "SigTimer.h"
+#include <pthread.h>
+
+typedef unsigned char uchar;
+typedef void (*MIDI_Callback_function)(int arrivalPort);
+
+
+class MidiInPort_oss : public Sequencer_oss {
+ public:
+ MidiInPort_oss (void);
+ MidiInPort_oss (int aPort, int autoOpen = 1);
+ ~MidiInPort_oss ();
+
+ void clearSysex (int buffer);
+ void clearSysex (void);
+ void close (void);
+ void close (int i) { close(); }
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static MIDI_Callback_function callbackFunction;
+
+ static int installSysexPrivate (int port,
+ uchar* anArray, int aSize);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* trace; // for verifying input
+ static std::ostream* tracedisplay; // stream for displaying trace
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>** midiBuffer; // MIDI storage frm ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* pauseQ; // for adding items to Buffer or not
+ static SigTimer midiTimer; // for timing MIDI input
+ static pthread_t midiInThread; // for MIDI input thread function
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+
+
+ friend void *interpretMidiInputStreamPrivate(void * x);
+
+};
+
+
+#endif /* LINUX */
+
+#endif /* _MIDIINPORT_OSS_H_INCLUDED */
+
+
+
+// md5sum: 05331ff5c3806fc753ebebaeffa3c377 - MidiInPort_oss.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_unsupported.h b/src/midiio/include/MidiInPort_unsupported.h
new file mode 100644
index 0000000..1f3bcf0
--- /dev/null
+++ b/src/midiio/include/MidiInPort_unsupported.h
@@ -0,0 +1,89 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Jan 23 00:04:51 GMT-0800 1998
+// Last Modified: Fri Jan 23 00:04:58 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_unsupported.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// an unknown sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+// This class is used when there is no MIDI input, so
+// that MIDI programs can otherwise be compiled and run.
+// This file can also serve as a template for creating
+// an OS specific class for MIDI input.
+//
+
+#ifndef _MIDIINPUT_UNSUPPORTED_H_INCLUDED
+#define _MIDIINPUT_UNSUPPORTED_H_INCLUDED
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+
+class MidiInPort_unsupported {
+ public:
+ MidiInPort_unsupported (void);
+ MidiInPort_unsupported (int aPort, int autoOpen = 1);
+ ~MidiInPort_unsupported ();
+
+ void clearSysex (int index) { }
+ void clearSysex (void) { }
+ int getSysexSize (int index) { return 0; }
+ uchar* getSysex (int buffer) { return NULL; }
+ int installSysex (unsigned char *&, int &) { return 0; }
+ int getBufferSize (void) { return 0; }
+ void close (void);
+ void close (int i) { close(); }
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace;
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of input ports
+ static CircularBuffer<MidiMessage>* midiBuffer; // MIDI storage from ports
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers; // for MIDI sysex storage
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+
+};
+
+
+
+#endif /* _MIDIINPUT_UNSUPPORTED_H_INCLUDED */
+
+
+
+// md5sum: ff5492fbd59a47e48e2c0ce06705add1 - MidiInPort_unsupported.h =css= 20030102
diff --git a/src/midiio/include/MidiInPort_visual.h b/src/midiio/include/MidiInPort_visual.h
new file mode 100644
index 0000000..398a187
--- /dev/null
+++ b/src/midiio/include/MidiInPort_visual.h
@@ -0,0 +1,114 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiInPort_visual.h
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// Windows 95/NT/98 specific MIDI input methods.
+// as defined in winmm.lib. This class is inherited
+// privately by the MidiInPort class.
+//
+
+#ifndef _MIDIINPUT_VISUAL_H_INCLUDED
+#define _MIDIINPUT_VISUAL_H_INCLUDED
+
+
+#ifdef VISUAL
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "MidiMessage.h"
+#include "CircularBuffer.h"
+#include "Array.h"
+
+class MidiInPort_visual {
+ public:
+ MidiInPort_visual (void);
+ MidiInPort_visual (int aPort, int autoOpen = 1);
+ ~MidiInPort_visual ();
+
+ void clearSysex (void);
+ void clearSysex (int buffer);
+ void close (void);
+ void closeAll (void);
+ MidiMessage extract (void);
+ int getBufferSize (void);
+ int getChannelOffset (void) const;
+ int getCount (void);
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ uchar* getSysex (int buffer);
+ int getSysexSize (int buffer);
+ int getTrace (void);
+ void insert (const MidiMessage& aMessage);
+ int installSysex (uchar* anArray, int aSize);
+ MidiMessage& message (int index);
+ int open (void);
+ void pause (void);
+ void setBufferSize (int aSize);
+ void setChannelOffset (int anOffset);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ void toggleTrace (void);
+ void unpause (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace;
+
+ int installSysexPrivate (int port, uchar* anArray, int aSize);
+ void installSysexStuff (HMIDIIN dev, int port);
+ void uninstallSysexStuff (HMIDIIN dev, int port);
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int* inrunningQ; // for running open input port
+ static int numDevices; // number of input ports
+ static HMIDIIN* device; // Windoze MIDI-in device structure
+ static MIDIHDR** sysexDriverBuffer1; // for Windoze driver sysex buffers
+ static MIDIHDR** sysexDriverBuffer2; // for Windoze driver sysex buffers
+ static int* sysexDBnumber; // for Windoze driver sysex buffers
+ static HANDLE* hMutex; // mutual exclusive
+ static CircularBuffer<MidiMessage>* midiBuffer; // MIDI storage from ports
+ static int channelOffset; // channel offset from either 0 or 1.
+ // not being used right now.
+ static int* sysexWriteBuffer; // for MIDI sysex write location
+ static Array<uchar>** sysexBuffers;// for MIDI sysex storage
+ static int* sysexStatus; // tracing multiple MIM_LONGDATA messgs
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void releaseMutex (void);
+ void setPortStatus (int aStatus);
+ void waitForMutex (void);
+
+
+ friend void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
+};
+
+
+// This is the command which is called by the driver when there is
+// MIDI data being received from the MIDI input port:
+ void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
+
+
+#endif /* VISUAL */
+#endif /* _MIDIINPUT_VISUAL_H_INCLUDED */
+
+
+
+// md5sum: d5aee7a88c4a054b3e2d4d40622fdc42 - MidiInPort_visual.h =css= 20030102
diff --git a/src/midiio/include/MidiInput.h b/src/midiio/include/MidiInput.h
new file mode 100644
index 0000000..4425f75
--- /dev/null
+++ b/src/midiio/include/MidiInput.h
@@ -0,0 +1,53 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Sun Jan 25 15:27:02 GMT-0800 1998
+// Last Modified: Thu Apr 20 16:23:24 PDT 2000 (added scale function)
+// Filename: ...sig/code/control/MidiInput/MidiInput.h
+// Web Address: http://sig.sapp.org/include/sig/MidiInput.h
+// Syntax: C++
+//
+// Description: A higher-level MIDI input interface than the
+// MidiInPort class. Can be used to allow multiple
+// objects to share a single MIDI input stream, or
+// to fake a MIDI input connection.
+//
+
+#ifndef _MIDIINPUT_H_INCLUDED
+#define _MIDIINPUT_H_INCLUDED
+
+
+#include "MidiInPort.h"
+
+
+class MidiInput : public MidiInPort {
+ public:
+ MidiInput (void);
+ MidiInput (int aPort, int autoOpen = 1);
+ ~MidiInput ();
+
+ int getBufferSize (void);
+ int getCount (void);
+ MidiMessage extract (void);
+ void insert (const MidiMessage& aMessage);
+ int isOrphan (void) const;
+ void makeOrphanBuffer (int aSize = 1024);
+ void removeOrphanBuffer(void);
+ void setBufferSize (int aSize);
+
+ int scale (int value, int min, int max);
+ double fscale (int value, double min, double max);
+ int scale14 (int value, int min, int max);
+ double fscale14 (int value, double min, double max);
+
+ protected:
+ CircularBuffer<MidiMessage>* orphanBuffer;
+
+};
+
+
+#endif /* _MIDIINPUT_H_INCLUDED */
+
+
+
+// md5sum: 73972cc29d7bcf0fba136b098c0419a0 - MidiInput.h =css= 20030102
diff --git a/src/midiio/include/MidiMessage.h b/src/midiio/include/MidiMessage.h
new file mode 100644
index 0000000..e4b59ba
--- /dev/null
+++ b/src/midiio/include/MidiMessage.h
@@ -0,0 +1,78 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Fri Jan 23 00:21:24 GMT-0800 1998
+// Last Modified: Sun Sep 20 20:30:53 PDT 1998
+// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions)
+// Filename: ...sig/include/sigInfo/MidiMessage.h
+// Web Address: http://sig.sapp.org/include/sigInfo/MidiMessage.h
+// Syntax: C++
+//
+// Description: A structure for handling MIDI input messages.
+// This class stores a time stamp plus up to
+// four MIDI message bytes. System Exclusive messages
+// are stored in a separate array in the MidiInPort
+// class, and their storage index is passed to the
+// user through a MIDI message for later extraction
+// of the full sysex message.
+//
+
+#ifndef _MIDIMESSAGE_H_INCLUDED
+#define _MIDIMESSAGE_H_INCLUDED
+
+#include <iostream>
+
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+
+class MidiMessage {
+ public:
+ ulong time; // timestamp
+ ulong data; // MIDI command and parameters
+
+ MidiMessage (void);
+ MidiMessage (int aCommand, int aP1, int aP2,
+ int aTime = 0);
+ MidiMessage (const MidiMessage& aMessage);
+ ~MidiMessage ();
+
+ uchar& command (void);
+ MidiMessage& operator= (const MidiMessage& aMessage);
+ uchar& operator[] (int index);
+ uchar& p0 (void);
+ uchar& p1 (void);
+ uchar& p2 (void);
+ uchar& p3 (void);
+ int getArgCount (void) const;
+ int getParameterCount (void) const;
+
+ uchar getCommand (void) const;
+ uchar getP0 (void) const;
+ uchar getP1 (void) const;
+ uchar getP2 (void) const;
+ uchar getP3 (void) const;
+
+ void setCommand (uchar aCommand);
+ void setData (uchar aCommand, uchar aP1 = 0,
+ uchar aP2 = 0, uchar aP3 = 0);
+ void setP0 (uchar aP0);
+ void setP1 (uchar aP1);
+ void setP2 (uchar aP2);
+ void setP3 (uchar aP3);
+
+ int is_note (void);
+ int is_note_on (void);
+ int is_note_off (void);
+
+};
+
+
+std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage);
+
+
+#endif /* _MIDIMESSAGE_H_INCLUDED */
+
+
+
+// md5sum: 4738e957fb8a233f6dbaeebda490e6a4 - MidiMessage.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort.h b/src/midiio/include/MidiOutPort.h
new file mode 100644
index 0000000..0287dfd
--- /dev/null
+++ b/src/midiio/include/MidiOutPort.h
@@ -0,0 +1,92 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:04:24 GMT-0800 1997
+// Last Modified: Fri Jan 23 10:56:18 GMT-0800 1998
+// Last Modified: Sat Nov 7 16:15:54 PST 1998
+// Last Modified: Tue May 23 23:08:44 PDT 2000 (oss/alsa selection added)
+// Last Modified: Mon Jun 19 10:32:11 PDT 2000 (oss/alsa define fix)
+// Filename: ...sig/code/control/MidiOutPort/MidiOutPort.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort.h
+// Syntax: C++
+//
+// Description: Operating-System independent interface for
+// basic MIDI output capabilities. Privately
+// inherits the operating-system specific class
+// for MIDI output.
+//
+
+#ifndef _MIDIOUTPORT_H_INCLUDED
+#define _MIDIOUTPORT_H_INCLUDED
+
+
+#ifdef VISUAL
+ #define MIDIOUTPORT MidiOutPort_visual
+ #include "MidiOutPort_visual.h"
+#elif defined(LINUX) && defined(ALSA) && defined(OSS)
+ #define MIDIOUTPORT MidiOutPort_linux
+ #include "MidiOutPort_linux.h"
+#elif defined(LINUX) && defined(ALSA) && !defined(OSS)
+ #define MIDIOUTPORT MidiOutPort_alsa
+ #include "MidiOutPort_alsa.h"
+#elif defined (LINUX) && defined(OSS) && !defined(ALSA)
+ #define MIDIOUTPORT MidiOutPort_oss
+ #include "MidiOutPort_oss.h"
+#elif defined(LINUX)
+ #define MIDIOUTPORT MidiOutPort_oss
+ #include "MidiOutPort_oss.h"
+#else
+ #define MIDIOUTPORT MidiOutPort_unsupported
+ #include "MidiOutPort_unsupported.h"
+#endif
+
+
+class MidiOutPort : protected MIDIOUTPORT {
+ public:
+ MidiOutPort (void) : MIDIOUTPORT() {}
+ MidiOutPort (int aPort, int autoOpen = 1) :
+ MIDIOUTPORT(aPort, autoOpen) {}
+ ~MidiOutPort() { }
+
+ void close(void) { MIDIOUTPORT::close(); }
+ void closeAll(void) { MIDIOUTPORT::closeAll(); }
+ int getChannelOffset(void) const {
+ return MIDIOUTPORT::getChannelOffset(); }
+ const char* getName(void) { return MIDIOUTPORT::getName(); }
+ static const char* getName(int i) { return MIDIOUTPORT::getName(i); }
+ static int getNumPorts(void) { return MIDIOUTPORT::getNumPorts(); }
+ int getPort(void) { return MIDIOUTPORT::getPort(); }
+ int getPortStatus(void) {
+ return MIDIOUTPORT::getPortStatus(); }
+ int getTrace(void) {
+ return MIDIOUTPORT::getTrace(); }
+ int open(void) { return MIDIOUTPORT::open(); }
+ int rawsend(int command, int p1, int p2) {
+ return MIDIOUTPORT::rawsend(command, p1, p2); }
+ int rawsend(int command, int p1) {
+ return MIDIOUTPORT::rawsend(command, p1); }
+ int rawsend(int command) {
+ return MIDIOUTPORT::rawsend(command); }
+ int rawsend(uchar* array, int size) {
+ return MIDIOUTPORT::rawsend(array, size); }
+ void setAndOpenPort(int aPort) { setPort(aPort); open(); }
+// void setChannelOffset(int aChannel) {
+// MIDIOUTPORT::setChannelOffset(aChannel); }
+ void setPort(int aPort) { MIDIOUTPORT::setPort(aPort); }
+ int setTrace(int aState) {
+ return MIDIOUTPORT::setTrace(aState); }
+ int sysex(uchar* array, int size) {
+ return MIDIOUTPORT::sysex(array, size); }
+ void toggleTrace(void) { MIDIOUTPORT::toggleTrace(); }
+ MidiOutPort& operator=(MidiOutPort& other) {
+ setPort(other.getPort());
+ if (other.getPortStatus()) { open(); }
+ return *this; }
+};
+
+
+
+
+#endif /* _MIDIOUTPORT_H_INCLUDED */
+
+
+// md5sum: 2f7b8aa8ef705eab57179b626ce1d62d - MidiOutPort.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_alsa.h b/src/midiio/include/MidiOutPort_alsa.h
new file mode 100644
index 0000000..34139a3
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_alsa.h
@@ -0,0 +1,79 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:22:00 PDT 2000
+// Last Modified: Sun May 14 20:43:44 PDT 2000
+// Last Modified: Sat Nov 2 20:39:01 PST 2002 (added ALSA def)
+// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_alsa.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPORT_ALSA_H_INCLUDED
+#define _MIDIOUTPORT_ALSA_H_INCLUDED
+
+#ifdef LINUX
+#ifdef ALSA
+
+#include "Sequencer_alsa.h"
+#include <iostream>
+
+typedef unsigned char uchar;
+
+
+class MidiOutPort_alsa : public Sequencer_alsa {
+ public:
+ MidiOutPort_alsa (void);
+ MidiOutPort_alsa (int aPort, int autoOpen = 1);
+ ~MidiOutPort_alsa ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int numDevices; // number of output ports
+ static int* trace; // for printing messages to output
+ static std::ostream* tracedisplay; // for printing trace messages
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+
+#endif /* ALSA */
+#endif /* LINUX */
+#endif /* _MIDIOUTPUT_ALSA_H_INCLUDED */
+
+
+// md5sum: 5b7648c7b493df7cb0d1fae3bbb8be24 - MidiOutPort_alsa.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_linux.h b/src/midiio/include/MidiOutPort_linux.h
new file mode 100644
index 0000000..a02dc22
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_linux.h
@@ -0,0 +1,80 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:03:52 PDT 2000
+// Last Modified: Thu May 18 23:37:17 PDT 2000
+// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def)
+// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.h
+// Syntax: C++
+//
+// Description: Linux MIDI output class which detects which
+// type of MIDI drivers are available: either
+// ALSA or OSS.
+//
+
+#ifndef _MIDIOUTPORT_LINUX_H_INCLUDED
+#define _MIDIOUTPORT_LINUX_H_INCLUDED
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include "MidiOutPort_oss.h"
+#include "MidiOutPort_alsa.h"
+#include "MidiOutPort_unsupported.h"
+
+#define UNKNOWN_MIDI_SELECT 0 /* use dummy MIDI output */
+#define OSS_MIDI_SELECT 1 /* use OSS MIDI output */
+#define ALSA_MIDI_SELECT 2 /* use ALSA MIDI output */
+
+class MidiOutPort_linux {
+ public:
+ MidiOutPort_linux (void);
+ MidiOutPort_linux (int aPort, int autoOpen = 1);
+ ~MidiOutPort_linux ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ static int getNumPorts (void);
+ int getPort (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int open (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ void setAndOpenPort (int aPort);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ static int getSelect (void);
+ static int selectOSS (void);
+ static int selectALSA (void);
+ static int selectUnknown (void);
+
+ private:
+ static int current; // the type of MIDI out selected
+ static int alsaQ; // boolean for if ALSA is present
+ static int ossQ; // boolean for if OSS is present
+
+ static int objectCount;
+ static MidiOutPort_oss *oss_output;
+ static MidiOutPort_alsa *alsa_output;
+ static MidiOutPort_unsupported *unknown_output;
+
+ void determineDrivers (void);
+};
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+#endif /* _MIDIOUTPORT_LINUX_H_INCLUDED */
+
+
+// md5sum: c80f9f47c45a6d4a20b6549743cae9fb - MidiOutPort_linux.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_oss.h b/src/midiio/include/MidiOutPort_oss.h
new file mode 100644
index 0000000..22cf32d
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_oss.h
@@ -0,0 +1,75 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Dec 18 19:15:00 PST 1998
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/linux/MidiOutPort_oss.h
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_oss.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPORT_OSS_H_INCLUDED
+#define _MIDIOUTPORT_OSS_H_INCLUDED
+
+#ifdef LINUX
+
+#include "Sequencer_oss.h"
+
+typedef unsigned char uchar;
+
+
+class MidiOutPort_oss : public Sequencer_oss {
+ public:
+ MidiOutPort_oss (void);
+ MidiOutPort_oss (int aPort, int autoOpen = 1);
+ ~MidiOutPort_oss ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int numDevices; // number of output ports
+ static int* trace; // for printing messages to output
+ static std::ostream* tracedisplay; // for printing trace messages
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+
+#endif /* LINUX */
+#endif /* _MIDIOUTPUT_OSS_H_INCLUDED */
+
+
+// md5sum: f60183e23c49741e93d9b965bbe9a6d8 - MidiOutPort_oss.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_unsupported.h b/src/midiio/include/MidiOutPort_unsupported.h
new file mode 100644
index 0000000..a5e8c35
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_unsupported.h
@@ -0,0 +1,71 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Jan 12 21:36:26 GMT-0800 1998
+// Last Modified: Mon Jan 12 21:36:31 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_unsupported.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for basic MIDI output
+// capabilities in an unknown operating system. Privately
+// inherited by the MidiOutPort class. Used for compiling
+// and running MIDI programs on a computer with no
+// MIDI output.
+//
+
+#ifndef _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED
+#define _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED
+
+typedef unsigned char uchar;
+
+class MidiOutPort_unsupported {
+ public:
+ MidiOutPort_unsupported (void);
+ MidiOutPort_unsupported (int aPort, int autoOpen = 1);
+ ~MidiOutPort_unsupported ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void) const;
+ const char* getName (int i) const;
+ int getPort (void) const;
+ int getNumPorts (void) const;
+ int getPortStatus (void) const;
+ int getTrace (void) const;
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace; // for printing out midi messages to standard output
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of output ports
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1
+ // not being used right now.
+};
+
+
+
+#endif /* _MIDIOUTPUT_UNSUPPORTED_H_INCLUDED */
+
+
+
+// md5sum: e244688a99d220addc7b1c6f6f6a8022 - MidiOutPort_unsupported.h =css= 20030102
diff --git a/src/midiio/include/MidiOutPort_visual.h b/src/midiio/include/MidiOutPort_visual.h
new file mode 100644
index 0000000..d6a3984
--- /dev/null
+++ b/src/midiio/include/MidiOutPort_visual.h
@@ -0,0 +1,75 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 20:05:27 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutPort_visual.h
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Windows 95/NT/98
+// using winmm.lib. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifndef _MIDIOUTPUT_VISUAL_H_INCLUDED
+#define _MIDIOUTPUT_VISUAL_H_INCLUDED
+
+#ifdef VISUAL
+
+typedef unsigned char uchar;
+
+#include <windows.h>
+#include <mmsystem.h>
+
+class MidiOutPort_visual {
+ public:
+ MidiOutPort_visual (void);
+ MidiOutPort_visual (int aPort, int autoOpen = 1);
+ ~MidiOutPort_visual ();
+
+ void close (void);
+ void closeAll (void);
+ int getChannelOffset (void) const;
+ const char* getName (void);
+ static const char* getName (int i);
+ int getPort (void);
+ static int getNumPorts (void);
+ int getPortStatus (void);
+ int getTrace (void);
+ int rawsend (int command, int p1, int p2);
+ int rawsend (int command, int p1);
+ int rawsend (int command);
+ int rawsend (uchar* array, int size);
+ int open (void);
+ void setChannelOffset (int aChannel);
+ void setPort (int aPort);
+ int setTrace (int aState);
+ int sysex (uchar* array, int size);
+ void toggleTrace (void);
+
+ protected:
+ int port; // the port to which this object belongs
+ int trace; // for printing out Midi messages to standard output
+
+ static int objectCount; // num of similar objects in existence
+ static int* portObjectCount; // objects connected to particular port
+ static int* openQ; // for open/close status of port
+ static int numDevices; // number of output ports
+ static HMIDIOUT* device; // Windoze midi out device structure
+
+ private:
+ void deinitialize (void);
+ void initialize (void);
+ void setPortStatus (int aStatus);
+
+ static int channelOffset; // channel offset, either 0 or 1.
+ // not being used right now.
+};
+
+
+#endif /* VISUAL */
+#endif /* _MIDIOUTPUT_VISUAL_H_INCLUDED */
+
+
+// md5sum: 47799e340effa57676be8a3943cabb70 - MidiOutPort_visual.h =css= 20030102
diff --git a/src/midiio/include/MidiOutput.h b/src/midiio/include/MidiOutput.h
new file mode 100644
index 0000000..d424816
--- /dev/null
+++ b/src/midiio/include/MidiOutput.h
@@ -0,0 +1,140 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Mon Jan 26 23:53:05 GMT-0800 1998
+// Last Modified: Sat Jan 30 14:00:29 PST 1999
+// Last Modified: Sun Jul 18 18:52:42 PDT 1999 (added RPN functions)
+// Filename: ...sig/maint/code/control/MidiOutput/MidiOutput.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiOutput.h
+// Syntax: C++
+//
+// Description: The MIDI output interface for MIDI synthesizers/equipment
+// which has many convienience functions defined for
+// various types of MIDI output.
+//
+
+#ifndef _MIDIOUTPUT_H_INCLUDED
+#define _MIDIOUTPUT_H_INCLUDED
+
+#include "MidiOutPort.h"
+#include "FileIO.h"
+#include "SigTimer.h"
+#include "Array.h"
+
+
+class MidiOutput : public MidiOutPort {
+ public:
+ MidiOutput (void);
+ MidiOutput (int aPort, int autoOpen = 1);
+ ~MidiOutput ();
+
+ // Basic user MIDI output commands:
+ int cont (int channel, int controller, int data);
+ int off (int channel, int keynum, int releaseVelocity);
+ int pc (int channel, int timbre);
+ int play (int channel, int keynum, int velocity);
+ int pw (int channel, int mostByte, int leastByte);
+ int pw (int channel, int tuningData);
+ int pw (int channel, double tuningData);
+ void recordStart (char *filename, int format);
+ void recordStop (void);
+ void reset (void);
+ int send (int command, int p1, int p2);
+ int send (int command, int p1);
+ int send (int command);
+ void silence (int aChannel = -1);
+ void sustain (int channel, int status);
+ int sysex (char* data, int length);
+ int sysex (uchar* data, int length);
+
+ protected:
+ int outputRecordQ; // boolean for recording
+ int outputRecordType; // what form to record MIDI data in
+ int lastFlushTime; // for recording midi data
+ FileIO outputRecordFile; // file for recording midi data
+ static SigTimer timer; // for recording midi data
+ static Array<int>* rpn_lsb_status; // for RPN messages
+ static Array<int>* rpn_msb_status; // for RPN messages
+ static int objectCount; // for RPN messages
+
+ void deinitializeRPN (void);
+ void initializeRPN (void);
+ void writeOutputAscii (int channel, int p1, int p2);
+ void writeOutputBinary (int channel, int p1, int p2);
+ void writeOutputMidifile(int channel, int p1, int p2);
+
+ public: // RPN controller functions
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb, int data_lsb);
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb);
+ int NRPN (int channel, int nrpn_msb, int nrpn_lsb,
+ double data);
+ int NRPN_null (int channel);
+ int NRPN_attack (int channel, double value);
+ int NRPN_attack (int channel, int value);
+ int NRPN_decay (int channel, double value);
+ int NRPN_decay (int channel, int value);
+ int NRPN_drumAttack (int drum, double value);
+ int NRPN_drumAttack (int drum, int value);
+ int NRPN_drumChorus (int drum, double value);
+ int NRPN_drumChorus (int drum, int value);
+ int NRPN_drumDecay (int drum, double value);
+ int NRPN_drumDecay (int drum, int value);
+ int NRPN_drumLevel (int drum, double value);
+ int NRPN_drumLevel (int drum, int value);
+ int NRPN_drumPan (int drum, double value);
+ int NRPN_drumPan (int drum, int value);
+ int NRPN_drumPitch (int drum, double value);
+ int NRPN_drumPitch (int drum, int value);
+ int NRPN_drumFilterCutoff (int drum, double value);
+ int NRPN_drumFilterCutoff (int drum, int value);
+ int NRPN_drumFilterResonance(int drum, double value);
+ int NRPN_drumFilterResonance(int drum, int value);
+ int NRPN_drumReverb (int drum, double value);
+ int NRPN_drumReverb (int drum, int value);
+ int NRPN_drumVariation (int drum, double value);
+ int NRPN_drumVariation (int drum, int value);
+ int NRPN_filterCutoff (int channel, double value);
+ int NRPN_filterCutoff (int channel, int value);
+ int NRPN_release (int channel, double value);
+ int NRPN_release (int channel, int value);
+ int NRPN_vibratoDelay (int channel, double value);
+ int NRPN_vibratoDelay (int channel, int value);
+ int NRPN_vibratoDepth (int channel, double value);
+ int NRPN_vibratoDepth (int channel, int value);
+ int NRPN_vibratoRate (int channel, double value);
+ int NRPN_vibratoRate (int channel, int value);
+
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ int data_msb, int data_lsb);
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ int data_msb);
+ int RPN (int channel, int rpn_msb, int rpn_lsb,
+ double data);
+ int RPN_null (void);
+ int RPN_null (int channel);
+ int pbRange (int channel, int steps);
+ int tuneFine (int channel, int cents);
+ int fineTune (int channel, int cents);
+ int tuneCoarse (int channel, int steps);
+ int coarseTune (int channel, int steps);
+ int tuningProgram (int channel, int program);
+ int tuningBank (int channel, int bank);
+
+};
+
+
+#endif /* _MIDIOUTPUT_H_INCLUDED */
+
+// Brief description of MidiOutput public member functions:
+//
+// send: sends a MIDI command to the MIDI output with up to two parameters
+// play: sends a playnote command to the MIDI output
+// pc: Patch Change. changes the timbre (instrument) on the given channel
+// cont: sends a CONTinuous CONTroller MIDI command
+// sysex: sends a system exclusive command to the MIDI output
+//
+
+
+// md5sum: 12ee02c32563ae219aaa8c7599de55db - MidiOutput.h =css= 20030102
diff --git a/src/midiio/include/MidiPort.h b/src/midiio/include/MidiPort.h
new file mode 100644
index 0000000..834877e
--- /dev/null
+++ b/src/midiio/include/MidiPort.h
@@ -0,0 +1,49 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Fri Jan 23 10:21:25 GMT-0800 1998
+// Filename: .../sig/code/control/MidiPort/MidiPort.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/MidiPort.h
+// Syntax: C++
+//
+// Description: A unified object that handles basic MIDI input and output.
+// Derived from the MidiInPort and MidiOutPort classes.
+//
+
+#ifndef _MIDIPORT_H_INCLUDED
+#define _MIDIPORT_H_INCLUDED
+
+
+#include "MidiInPort.h"
+#include "MidiOutPort.h"
+
+
+class MidiPort : public MidiOutPort, public MidiInPort {
+ public:
+ MidiPort (void);
+ MidiPort (int outputPort, int inputPort);
+ ~MidiPort ();
+
+ int getChannelInOffset (void) const;
+ int getChannelOutOffset (void) const;
+ int getInputPort (void);
+ int getInputTrace (void);
+ int getOutputPort (void);
+ int getOutputTrace (void);
+ void setChannelOffset (int anOffset);
+ void setInputPort (int aPort);
+ int setInputTrace (int aState);
+ void setOutputPort (int aPort);
+ int setOutputTrace (int aState);
+ void toggleInputTrace (void);
+ void toggleOutputTrace (void);
+
+};
+
+
+
+#endif /* _MIDIPORT_H_INCLUDED */
+
+
+
+// md5sum: 84d8155528b06c9aa902e8f06649385f - MidiPort.h =css= 20030102
diff --git a/src/midiio/include/Options.h b/src/midiio/include/Options.h
new file mode 100644
index 0000000..71754fb
--- /dev/null
+++ b/src/midiio/include/Options.h
@@ -0,0 +1,106 @@
+//
+// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Fri Jan 15 07:24:00 PST 1999
+// Last Modified: Sat Mar 27 18:17:59 PST 1999
+// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function)
+// Last Modified: Fri May 5 17:57:50 PDT 2000 (added --options suppression)
+// Filename: ...sig/maint/code/base/Options/Options.h
+// Web Address: http://sig.sapp.org/include/sigBase/Options.h
+// Documentation: http://sig.sapp.org/doc/classes/Options
+// Syntax: C++
+//
+// Description: Handles command-line options in a graceful manner.
+//
+
+#ifndef _OPTIONS_H_INCLUDED
+#define _OPTIONS_H_INCLUDED
+
+#include "Array.h"
+
+class option_list;
+class option_register;
+
+
+class Options {
+ public:
+ Options (void);
+ Options (int argc, char** argv);
+ ~Options ();
+
+ int argc (void) const;
+ char** argv (void) const;
+ void define (const char* aDefinition);
+ void define (const char* aDefinition,
+ const char* description);
+ char* getArg (int index);
+ char* getArgument (int index);
+ int getArgCount (void);
+ int getArgumentCount (void);
+ int getBoolean (const char* optionName);
+ const char* getCommand (void);
+ const char* getCommandLine (void);
+ const char* getString (void);
+ const char* getDefinition (const char* optionName);
+ double getDouble (const char* optionName);
+ char getFlag (void);
+ float getFloat (const char* optionName);
+ int getInt (const char* optionName);
+ int getInteger (const char* optionName);
+ const char* getString (const char* optionName);
+ char getType (const char* optionName);
+ int optionsArg (void);
+ void print (void);
+ void process (int error_check = 1, int suppress = 0);
+ void process (int argc, char** argv,
+ int error_check = 1,
+ int suppress = 0);
+ void reset (void);
+ void verify (int argc, char** argv,
+ int error_check = 1,
+ int suppress = 0);
+ void verify (int error_check = 1,
+ int suppress = 0);
+ void setFlag (char aFlag);
+ void setModified (const char* optionName,
+ const char* optionValue);
+ void setOptions (int argc, char** argv);
+
+ protected:
+ int options_error_check; // for verify command
+ int gargc;
+ char** gargv;
+ char* commandString;
+ char optionFlag;
+ Array<char*> argument;
+ Array<option_register*> optionRegister;
+ Array<option_list*> optionList;
+ int processedQ;
+ int sortedQ;
+ int suppressQ; // prevent the --options option
+ int optionsArgument; // indicates --options present
+
+ int getRegIndex (const char* optionName);
+ int optionQ (const char* aString, int& argp);
+ void sortOptionNames (void);
+ int storeOption (int gargp, int& position,
+ int& running);
+
+};
+
+#define OPTION_BOOLEAN_TYPE 'b'
+#define OPTION_CHAR_TYPE 'c'
+#define OPTION_DOUBLE_TYPE 'd'
+#define OPTION_FLOAT_TYPE 'f'
+#define OPTION_INT_TYPE 'i'
+#define OPTION_STRING_TYPE 's'
+#define OPTION_UNKNOWN_TYPE 'x'
+
+
+
+#endif /* _OPTIONS_H_INCLUDED */
+
+
+
+// md5sum: c59d297a8081cb48f61b534484819f48 - Options.h =css= 20030102
diff --git a/src/midiio/include/Options_private.h b/src/midiio/include/Options_private.h
new file mode 100644
index 0000000..8349d55
--- /dev/null
+++ b/src/midiio/include/Options_private.h
@@ -0,0 +1,73 @@
+//
+// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sun Jan 10 05:44:48 PST 1999
+// Filename: ...sig/maint/code/base/Options/Options_private.h
+// Web Address: http://sig.sapp.org/include/sigBase/Options_private.h
+// Syntax: C++
+//
+// Description: A private function for use in the Options class.
+//
+
+#ifndef _OPTIONS_PRIVATE_H_INCLUDED
+#define _OPTIONS_PRIVATE_H_INCLUDED
+
+
+class option_register {
+ public:
+ option_register (void);
+ option_register (const char* aDefinition, char aType,
+ const char* aDefaultOption,
+ const char* aModifiedOption);
+ ~option_register ();
+ void clearModified (void);
+ const char* getDefinition (void);
+ const char* getDefault (void);
+ const char* getOption (void);
+ const char* getModified (void);
+ int getModifiedQ (void);
+ char getType (void);
+ void reset (void);
+ void setDefault (const char* aString);
+ void setDefinition (const char* aString);
+ void setModified (const char* aString);
+ void setType (char aType);
+
+ protected:
+ char* definition;
+ char* defaultOption;
+ char* modifiedOption;
+ char type;
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+class option_list {
+ public:
+ option_list (void);
+ option_list (const char* optionName, int anIndex);
+ ~option_list ();
+
+ int getIndex (void);
+ const char* getName (void);
+ void setName (const char* aString);
+ void setIndex (int anIndex);
+
+ protected:
+ char* name;
+ int index;
+
+};
+
+
+
+#endif /* _OPTIONS_PRIVATE_H_INCLUDED */
+
+
+
+// md5sum: b440ad2158e9921d0e31463a8c3e1ae0 - Options_private.h =css= 20030102
diff --git a/src/midiio/include/Sequencer_alsa.h b/src/midiio/include/Sequencer_alsa.h
new file mode 100644
index 0000000..3227f5e
--- /dev/null
+++ b/src/midiio/include/Sequencer_alsa.h
@@ -0,0 +1,139 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:06:21 PDT 2000
+// Last Modified: Sat Oct 13 14:50:04 PDT 2001 (updated for ALSA 0.9 interface)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_alsa.h
+// Web Address: http://sig.sapp.org/include/sig/Sequencer_alsa.h
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA midi device /dev/snd/midiXX. This class
+// is inherited by the classes MidiInPort_alsa and
+// MidiOutPort_alsa.
+//
+// to get information of status a alsa hardware & software
+// cat /proc/asound/version
+// cat /proc/asound/devices
+// cat /proc/asound/card0/midi0
+//
+
+#ifndef _SEQUENCER_ALSA_H_INCLUDED
+#define _SEQUENCER_ALSA_H_INCLUDED
+
+#include <iostream>
+
+#ifdef ALSA
+
+#include <alsa/asoundlib.h>
+#include "Collection.h"
+
+#define MIDI_EXTERNAL (1)
+#define MIDI_INTERNAL (2)
+
+typedef unsigned char uchar;
+
+
+class Sequencer_alsa {
+ public:
+ Sequencer_alsa (int autoOpen = 1);
+ ~Sequencer_alsa ();
+
+ void close (void);
+ void closeInput (int index);
+ void closeOutput (int index);
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ static const char* getInputName (int aDevice);
+ static const char* getOutputName (int aDevice);
+ static int getNumInputs (void);
+ static int getNumOutputs (void);
+ int is_open (int mode, int index);
+ int is_open_in (int index);
+ int is_open_out (int index);
+ int open (int direction, int index);
+ int openInput (int index);
+ int openOutput (int index);
+ void read (int dev, uchar* buf, int count);
+ void rebuildInfoDatabase (void);
+ int write (int aDevice, int aByte);
+ int write (int aDevice, uchar* bytes, int count);
+ int write (int aDevice, char* bytes, int count);
+ int write (int aDevice, int* bytes, int count);
+
+ int getInCardValue (int aDevice) const;
+ int getOutCardValue (int aDevice) const;
+ protected:
+ static int class_count; // number of existing classes using
+ static int indevcount; // number of MIDI input devices
+ static int outdevcount; // number of MIDI output devices
+ static int initialized; // for starting buileinfodatabase
+
+ static Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_in;
+ static Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_out;
+ static Collection<int> Sequencer_alsa::midiincard;
+ static Collection<int> Sequencer_alsa::midioutcard;
+ static Collection<int> Sequencer_alsa::midiindevice;
+ static Collection<int> Sequencer_alsa::midioutdevice;
+ static Collection<char*> Sequencer_alsa::midiinname;
+ static Collection<char*> Sequencer_alsa::midioutname;
+
+ private:
+ static void buildInfoDatabase (void);
+ static void getPossibleMidiStreams(Collection<int>& cards,
+ Collection<int>& devices);
+ int getInDeviceValue (int aDevice) const;
+ int getInputType (int aDevice) const;
+ int getOutDeviceValue (int aDevice) const;
+ int getOutputType (int aDevice) const;
+ void removeInfoDatabase (void);
+
+
+ friend void *interpretMidiInputStreamPrivateALSA(void * x);
+
+};
+
+#else /* ALSA is not defined */
+
+typedef unsigned char uchar;
+
+class Sequencer_alsa {
+ public:
+ Sequencer_alsa (int autoOpen = 1) { }
+ ~Sequencer_alsa () { }
+
+ void close (void) { };
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t")
+ { out << initial << "NONE\n"; }
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t")
+ { out << initial << "NONE\n"; }
+ static const char* getInputName (int aDevice) { return ""; }
+ static const char* getOutputName (int aDevice) { return ""; }
+ static int getNumInputs (void) { return 0; }
+ static int getNumOutputs (void) { return 0; }
+ int is_open (int mode, int index) { return 0; }
+ int is_open_in (int index) { return 0; }
+ int is_open_out (int index) { return 0; }
+ int open (void) { return 0; }
+ void read (int dev, uchar* buf, int count) { }
+ void rebuildInfoDatabase (void) { }
+ int write (int aDevice, int aByte) { return 0; }
+ int write (int aDevice, uchar* bytes, int count) { return 0; }
+ int write (int aDevice, char* bytes, int count) { return 0; }
+ int write (int aDevice, int* bytes, int count) { return 0; }
+ int getInCardValue (int aDevice) const { return 0; }
+ int getOutCardValue (int aDevice) const { return 0; }
+
+};
+
+
+#endif /* ALSA */
+
+
+#endif /* _SEQUENCER_ALSA_H_INCLUDED */
+
+
+// md5sum: 6147020b0646fca8245f653505308949 - Sequencer_alsa.h =css= 20030102
diff --git a/src/midiio/include/Sequencer_oss.h b/src/midiio/include/Sequencer_oss.h
new file mode 100644
index 0000000..5f269a7
--- /dev/null
+++ b/src/midiio/include/Sequencer_oss.h
@@ -0,0 +1,92 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Jan 3 21:02:02 PST 1999
+// Last Modified: Sat Jan 30 14:11:18 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _oss to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.h
+// Web Address: http://sig.sapp.org/include/sig/Sequencer_oss.h
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux OSS midi device /dev/sequencer. This class
+// is inherited by the classes MidiInPort_oss and
+// MidiOutPort_oss.
+//
+
+#ifndef _SEQUENCER_OSS_H_INCLUDED
+#define _SEQUENCER_OSS_H_INCLUDED
+
+#include <iostream>
+
+#define MIDI_EXTERNAL (1)
+#define MIDI_INTERNAL (2)
+
+typedef unsigned char uchar;
+
+
+class Sequencer_oss {
+ public:
+ Sequencer_oss (int autoOpen = 1);
+ ~Sequencer_oss ();
+
+ void close (void);
+ void displayInputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ void displayOutputs (std::ostream& out = std::cout,
+ char* initial = "\t");
+ static int getNumInputs (void);
+ static int getNumOutputs (void);
+ static const char* getInputName (int aDevice);
+ static const char* getOutputName (int aDevice);
+ int is_open (void);
+ int open (void);
+ void read (uchar* buf, uchar* dev, int count);
+ void rawread (uchar* buf, int packetCount);
+ void rebuildInfoDatabase (void);
+ int write (int aDevice, int aByte);
+ int write (int aDevice, uchar* bytes, int count);
+ int write (int aDevice, char* bytes, int count);
+ int write (int aDevice, int* bytes, int count);
+
+ protected:
+ static const char* sequencer; // name of sequencer device
+ static int sequencer_fd; // sequencer file descriptor
+ static int class_count; // number of existing classes using
+ static uchar midi_write_packet[4]; // for writing MIDI bytes out
+ static uchar midi_read_packet[4]; // for reading MIDI bytes out
+ static uchar synth_write_message[8]; // for writing to internal seq
+ static int indevcount; // number of MIDI input devices
+ static int outdevcount; // number of MIDI output devices
+ static char** indevnames; // MIDI input device names
+ static char** outdevnames; // MIDI output device names
+ static int* indevnum; // total number of MIDI inputs
+ static int* outdevnum; // total number of MIDI outputs
+ static int* indevtype; // 1 = External, 2 = Internal
+ static int* outdevtype; // 1 = External, 2 = Internal
+ static uchar synth_message_buffer[1024]; // hold bytes for synth dev
+ static int synth_message_buffer_count; // count of synth buffer
+ static int synth_message_bytes_expected; // expected count of synth
+ static int synth_message_curr_device; // for keeping track of dev
+ static int initialized; // for starting buileinfodatabase
+
+ private:
+ static void buildInfoDatabase (void);
+ static int getFd (void);
+ int getInDeviceValue (int aDevice) const;
+ int getInputType (int aDevice) const;
+ int getOutDeviceValue (int aDevice) const;
+ int getOutputType (int aDevice) const;
+ void removeInfoDatabase (void);
+ void setFd (int anFd);
+
+ int writeInternal(int aDevice, int aByte);
+ int transmitMessageToInternalSynth(void);
+ int transmitVoiceMessage(void);
+ int transmitCommonMessage(void);
+};
+
+
+#endif /* _SEQUENCER_OSS_H_INCLUDED */
+
+
+// md5sum: 1df08cd946c609b9b42aadbc96b7a296 - Sequencer_oss.h =css= 20030102
diff --git a/src/midiio/include/SigTimer.h b/src/midiio/include/SigTimer.h
new file mode 100644
index 0000000..e93345c
--- /dev/null
+++ b/src/midiio/include/SigTimer.h
@@ -0,0 +1,104 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Thanks to: Erik Neuenschwander <erikn@leland.stanford.edu>
+// for Windows 95 assembly code for Pentium clock cycles.
+// Ozgur Izmirli <ozgur@ccrma.stanford.edu>
+// for concept of periodic timer.
+// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997
+// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998
+// Last Modified: Sat Sep 19 15:56:48 PDT 1998
+// Last Modified: Mon Feb 22 04:44:25 PST 1999
+// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod())
+// Filename: .../sig/code/control/SigTimer/SigTimer.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/SigTimer.h
+// Syntax: C++
+//
+// Description: This class can only be used on Motorola Pentinum 75 Mhz
+// chips or better because the timing information is
+// extracted from the clock cycle count from a register
+// on the CPU itself. This class will estimate the
+// speed of the computer, but it would be better if there
+// was a way of finding out the speed from some function.
+// This class is used primarily for timing of MIDI input
+// and output at a millisecond resolution.
+//
+// Interesting: http://www.datasilicon.nl/I786/timer_1.htm
+//
+
+#ifndef _SIGTIMER_H_INCLUDED
+#define _SIGTIMER_H_INCLUDED
+
+
+#ifdef VISUAL
+ #include <wtypes.h>
+ typedef LONGLONG int64bits;
+#else
+ typedef long long int int64bits;
+ #include <unistd.h> /* for millisleep function */
+#endif
+
+
+class SigTimer {
+ public:
+ SigTimer (void);
+ SigTimer (int aSpeed);
+ SigTimer (SigTimer& aTimer);
+ ~SigTimer ();
+
+ void adjustPeriod (double periodDelta);
+ int expired (void) const;
+ double getPeriod (void) const;
+ double getPeriodCount (void) const;
+ double getTempo (void) const;
+ int getTicksPerSecond (void) const;
+ int getTime (void) const;
+ double getTimeInSeconds (void) const;
+ int getTimeInTicks (void) const;
+ void reset (void);
+ void setPeriod (double aPeriod);
+ void setTempo (double beatsPerMinute);
+ void setPeriodCount (double aCount);
+ void setTicksPerSecond (int aTickRate);
+ void start (void);
+ void sync (SigTimer& aTimer);
+ void update (void);
+ void update (int periodCount);
+
+ // The following functions are semi-private. They do not have
+ // anything to do with timing themselves, but are a by-product
+ // of the timer implementation. They are useful, so they have
+ // been left public; however, they should be used judiciously.
+ static int getCpuSpeed (void);
+ static int measureCpuSpeed (int quantize = 0);
+ static void setCpuSpeed (int aSpeed);
+
+ // the following function is hardware specific to Intel Pentium
+ // computers with a processor speed of at least 75 MHz.
+ // This function is the only non-portable function in this
+ // class, but everything else is based on it.
+ static int64bits clockCycles (void);
+
+ protected:
+ static int64bits globalOffset;
+ static int cpuSpeed;
+
+ int64bits offset;
+ int ticksPerSecond;
+ double period;
+
+ // protected functions
+ double getFactor (void) const;
+
+};
+
+
+// The following function is mostly for Linux:
+void millisleep(int milliseconds);
+void millisleep(float milliseconds);
+
+
+#endif /* _SIGTIMER_H_INCLUDED */
+
+
+
+// md5sum: 601fa3caae4e3bacc4e6fb87f545c86b - SigTimer.h =css= 20030102
diff --git a/src/midiio/include/Voice.h b/src/midiio/include/Voice.h
new file mode 100644
index 0000000..3cddf9f
--- /dev/null
+++ b/src/midiio/include/Voice.h
@@ -0,0 +1,70 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Oct 11 18:21:46 PDT 1998
+// Last Modified: Sun Oct 11 18:33:04 PDT 1998
+// Filename: ...sig/maint/code/control/Voice/Voice.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/Voice.h
+// Syntax: C++
+//
+// Description: The Voice class is a MIDI output class which keeps
+// track of the last note played in to it. If the last
+// note was not turned off when a new note is played,
+// then the old note will be turned off before the
+// new note is played.
+//
+
+#ifndef _VOICE_H_INCLUDED
+#define _VOICE_H_INCLUDED
+
+#include "MidiOutput.h"
+
+class Voice : public MidiOutput {
+ public:
+ Voice (int aChannel);
+ Voice (const Voice& aVoice);
+ Voice (void);
+ ~Voice ();
+
+ void cont (int controler, int data);
+ int getChan (void) const;
+ int getChannel (void) const;
+ int getKey (void) const;
+ int getKeynum (void) const;
+ int getOffTime (void) const;
+ int getOnTime (void) const;
+ int getVel (void) const;
+ int getVelocity (void) const;
+ void off (void);
+ void pc (int aTimbre);
+ void play (int aChannel, int aKeyno, int aVelocity);
+ void play (int aKeyno, int aVelocity);
+ void play (void);
+ void setChan (int aChannel);
+ void setChannel (int aChannel);
+ void setKey (int aKeyno);
+ void setKeynum (int aKeyno);
+ void setVel (int aVelocity);
+ void setVelocity (int aVelocity);
+ int status (void) const;
+ void sustain (int aStatus);
+
+ protected:
+ int chan; // the current channel number
+ int key; // the current key number
+ int vel; // the current velocity value
+
+ int onTime; // last note on message sent
+ int offTime; // last note off message sent
+
+ int oldChan; // last channel played on
+ int oldKey; // last key to be played
+ int oldVel; // last velocity of last key
+
+ static SigTimer timer; // for recording on/off times
+};
+
+
+#endif /* _VOICE_H_INCLUDED */
+
+
+// md5sum: 8a5495ecc10d42be6b1832492e107723 - Voice.h =css= 20030102
diff --git a/src/midiio/include/gminstruments.h b/src/midiio/include/gminstruments.h
new file mode 100644
index 0000000..0e567da
--- /dev/null
+++ b/src/midiio/include/gminstruments.h
@@ -0,0 +1,251 @@
+//
+// Copyright 1997-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> (from 18Dec1997)
+// Creation Date: 26 December 1997
+// Last Modified: Tue Apr 18 11:38:28 PDT 2000 (put CH_X defines here)
+// Filename: ...sig/include/sigInfo/gminstruments.h
+// Web Address: http://sig.sapp.org/include/sigInfo/gminstruments.h
+// Syntax: C
+//
+// Description: Defines names for instruments as arranged in General MIDI.
+//
+
+#ifndef _GMINSTRUMENTS_H_INCLUDED
+#define _GMINSTRUMENTS_H_INCLUDED
+
+#define CH_1 0
+#define CH_2 1
+#define CH_3 2
+#define CH_4 3
+#define CH_5 4
+#define CH_6 5
+#define CH_7 6
+#define CH_8 7
+#define CH_9 8
+#define CH_10 9
+#define CH_11 10
+#define CH_12 11
+#define CH_13 12
+#define CH_14 13
+#define CH_15 14
+#define CH_16 15
+
+#define GM_PIANO(X) (0+(X))
+#define GM_ACOUSTIC_GRAND_PIANO (0)
+#define GM_BRIGHT_ACOUSTIC_PIANO (1)
+#define GM_ELECTRIC_GRAND_PIANO (1)
+#define GM_HONKYTONK_PIANO (2)
+#define GM_HONKY_TONK_PIANO (3)
+#define GM_ELECTRIC_PIANO_1 (4)
+#define GM_ELECTRIC_PIANO_2 (5)
+#define GM_HARPSICHORD (6)
+#define GM_CLAVI (7)
+
+#define GM_CHROMATIC(X) (8+(X))
+#define GM_CELESTA (8)
+#define GM_GLOCKENSPIEL (9)
+#define GM_MUSIC_BOX (10)
+#define GM_VIBRAPHONE (11)
+#define GM_MARIMBA (12)
+#define GM_XYLOPHONE (13)
+#define GM_TUBULAR_BELLS (14)
+#define GM_DULCIMER (15)
+
+#define GM_ORGAN(X) (16+(X))
+#define GM_DRAWBAR_ORGAN (16)
+#define GM_PERCUSSIVE_ORGAN (17)
+#define GM_ROCK_ORGAN (18)
+#define GM_CHURCH_ORGAN (19)
+#define GM_REED_ORGAN (20)
+#define GM_ACCORDION (21)
+#define GM_HARMONICA (22)
+#define GM_TANGO_ACCORDION (23)
+
+#define GM_GUITAR(X) (24+(X))
+#define GM_ACOUSTIC_GUITAR_NYLON (24)
+#define GM_ACOUSTIC_GUITAR_STEEL (25)
+#define GM_ELECTRIC_GUITAR_JAZZ (26)
+#define GM_ELECTRIC_GUITAR_CLEAN (27)
+#define GM_ELECTRIC_GUITAR_MUTED (28)
+#define GM_OVERDRIVEN_GUITAR (29)
+#define GM_DISTORTION_GUITAR (30)
+#define GM_GUITAR_HARMONICS (31)
+
+#define GM_BASS(X) (32+(X))
+#define GM_ACOUSTIC_BASS (32)
+#define GM_ELECTRIC_BASS_FINGER (33)
+#define GM_ELECTRIC_BASS_PICK (34)
+#define GM_FRETLESS_BASS (35)
+#define GM_SLAP_BASS_1 (36)
+#define GM_SLAP_BASS_2 (37)
+#define GM_SYNTH_BASS_1 (38)
+#define GM_SYNTH_BASS_2 (39)
+
+#define GM_STRINGS(X) (40+(X))
+#define GM_VIOLIN (40)
+#define GM_VIOLA (41)
+#define GM_CELLO (42)
+#define GM_CONTRABASS (43)
+#define GM_TREMOLO_STRINGS (44)
+#define GM_PIZZACATO_STRINGS (45)
+#define GM_ORCHESTRAL_HARP (46)
+#define GM_TIMPANI (47)
+
+#define GM_ENSEMBLE(X) (48+(X))
+#define GM_STRING_ENSEMBLE_1 (48)
+#define GM_STRING_ENSEMBLE_2 (49)
+#define GM_SYNTHSTRINGS_1 (50)
+#define GM_SYNTHSTRINGS_2 (51)
+#define GM_CHOIR_AAHS (52)
+#define GM_VOICE_OOHS (53)
+#define GM_SYNTH_VOICE (54)
+#define GM_ORCHESTRA_HIT (55)
+
+#define GM_BRASS(X) (56+(X))
+#define GM_TRUMPET (56)
+#define GM_TROMBONE (57)
+#define GM_TUBA (58)
+#define GM_MUTED_TRUMPED (59)
+#define GM_FRENCH_HORN (60)
+#define GM_BRASS_SECTION (61)
+#define GM_SYNTHBRASS_1 (62)
+#define GM_SYNTHBRASS_2 (63)
+
+#define GM_REED(X) (64+(X))
+#define GM_SOPRANO_SAX (64)
+#define GM_ALTO_SAX (65)
+#define GM_TENOR_SAX (66)
+#define GM_BARITONE_SAX (67)
+#define GM_OBOE (68)
+#define GM_ENGLISH_HORN (69)
+#define GM_BASSOON (70)
+#define GM_CLARINET (71)
+
+#define GM_PIPE(X) (72+(X))
+#define GM_PICCOLO (72)
+#define GM_FLUTE (73)
+#define GM_RECORDER (74)
+#define GM_PAN_FLUTE (75)
+#define GM_BLOWN_BOTTLE (76)
+#define GM_SHAKUHACHI (77)
+#define GM_WHISTLE (78)
+#define GM_OCARINA (79)
+
+#define GM_LEAD(X) (80+(X))
+#define GM_LEAD_SQUARE (80)
+#define GM_LEAD_SAWTOOTH (81)
+#define GM_LEAD_CALLIOPE (82)
+#define GM_LEAD_CHIFF (83)
+#define GM_LEAD_CHARANG (84)
+#define GM_LEAD_VOICE (85)
+#define GM_LEAD_FIFTHS (86)
+#define GM_LEAD_BASS (87)
+
+#define GM_PAD(X) (88+(X))
+#define GM_PAD_NEW_AGE (88)
+#define GM_PAD_WARM (89)
+#define GM_PAD_POLYSYNTH (90)
+#define GM_PAD_CHOIR (91)
+#define GM_PAD_BOWED (92)
+#define GM_PAD_METALLIC (93)
+#define GM_PAD_HALO (94)
+#define GM_PAD_SWEEP (95)
+
+#define GM_FX(X) (96+(X))
+#define GM_FX_TRAIN (96)
+#define GM_FX_SOUNDTRACK (97)
+#define GM_FX_CRYSTAL (98)
+#define GM_FX_ATMOSPHERE (99)
+#define GM_FX_BRIGHTNESS (100)
+#define GM_FX_GOBLINS (101)
+#define GM_FX_ECHOES (102)
+#define GM_FX_SCI_FI (103)
+
+#define GM_ETHNIC(X) (104+(X))
+#define GM_SITAR (104)
+#define GM_BANJO (105)
+#define GM_SHAMISEN (106)
+#define GM_KOTO (107)
+#define GM_KALIMBA (108)
+#define GM_BAGPIPE (109)
+#define GM_FIDDLE (110)
+#define GM_SHANAI (111)
+
+#define GM_PERCUSSION(X) (112+(X))
+#define GM_TINKLE_BELL (112)
+#define GM_AGOGO (113)
+#define GM_STEEL_DRUMS (114)
+#define GM_WOODBLOCKS (115)
+#define GM_TAIKO_DRUM (116)
+#define GM_MELODIC_DRUM (117)
+#define GM_SYNTH_DRUM (118)
+#define GM_REVERSE_CYMBAL (119)
+
+#define GM_SOUNDEFFECT(X) (120+(X))
+#define GM_GUITAR_FRET_NOISE (120)
+#define GM_BREATH_NOISE (121)
+#define GM_SEASHORE (122)
+#define GM_BIRD_TWEET (123)
+#define GM_TELEPHONE_RING (124)
+#define GM_HELICOPTER (125)
+#define GM_APPLAUSE (126)
+#define GM_GUNSHOT (127)
+
+//
+// Percussion instruments on channel 10
+//
+
+#define GM_ACOUSTIC_BASS_DRUM (35)
+#define GM_BASS_DRUM_1 (36)
+#define GM_SIDE_STICK (37)
+#define GM_ACOUSTIC_SNARE (38)
+#define GM_HAND_CLAP (39)
+#define GM_ELECTRIC_SNARE (40)
+#define GM_LOW_FLOOR_TOM (41)
+#define GM_CLOSED_HI_HAT (42)
+#define GM_HIGH_FLOOR_TOM (43)
+#define GM_PEDAL_HI_HAT (44)
+#define GM_LOW_TOM (45)
+#define GM_OPEN_HI_HAT (46)
+#define GM_LOW_MID_TOM (47)
+#define GM_HIGH_MID_TOM (48)
+#define GM_CRASH_CYMBAL_1 (49)
+#define GM_HIGH_TOM (50)
+#define GM_RIDE_CYMBAL_1 (51)
+#define GM_CHINESE_CYMBAL (52)
+#define GM_RIDE_BELL (53)
+#define GM_TAMBOURINE (54)
+#define GM_SPLASH_CYMBAL (55)
+#define GM_COWBELL (56)
+#define GM_CRASH_CYMBAL_2 (57)
+#define GM_VIBRASLAP (58)
+#define GM_RIDE_CYMBAL_2 (59)
+#define GM_HI_BONGO (60)
+#define GM_LOW_BONGO (61)
+#define GM_MUTE_HI_CONGA (62)
+#define GM_OPEN_HI_CONGA (63)
+#define GM_LOW_CONGA (64)
+#define GM_HIGH_TIMBALE (65)
+#define GM_LOW_TIMBALE (66)
+#define GM_HIGH_AGOGO (67)
+#define GM_LOW_AGOGO (68)
+#define GM_CABASA (69)
+#define GM_MARACAS (70)
+#define GM_SHORT_WHISTLE (71)
+#define GM_LONG_WHISTLE (72)
+#define GM_SHORT_GUIRO (73)
+#define GM_LONG_GUIRO (74)
+#define GM_CLAVES (75)
+#define GM_HI_WOOD_BLOCK (76)
+#define GM_LOW_WOOD_BLOCK (77)
+#define GM_MUTE_CUICA (78)
+#define GM_OPEN_CUICA (79)
+#define GM_MUTE_TRIANGLE (80)
+#define GM_OPEN_TRIANGLE (81)
+
+
+#endif /* _GMINSTRUMENTS_H_INCLUDED */
+
+
+
+// md5sum: 6299d04892a6899533b9164aa9e1a874 - gminstruments.h =css= 20030102
diff --git a/src/midiio/include/midichannels.h b/src/midiio/include/midichannels.h
new file mode 100644
index 0000000..4526813
--- /dev/null
+++ b/src/midiio/include/midichannels.h
@@ -0,0 +1,42 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998
+// Filename: ...sig/code/control/misc/midichannels.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/midichannels.h
+// Syntax: C++
+//
+// Description: Offset by 1 MIDI channel names.
+//
+
+#ifndef _MIDICHANNELS_H_INCLUDED
+#define _MIDICHANNELS_H_INCLUDED
+
+/* temporarily changed :
+
+// channel defines: offset from 0
+#define CH_1 (0x00)
+#define CH_2 (0x01)
+#define CH_3 (0x02)
+#define CH_4 (0x03)
+#define CH_5 (0x04)
+#define CH_6 (0x05)
+#define CH_7 (0x06)
+#define CH_8 (0x07)
+#define CH_9 (0x08)
+#define CH_10 (0x09)
+#define CH_11 (0x0a)
+#define CH_12 (0x0b)
+#define CH_13 (0x0c)
+#define CH_14 (0x0d)
+#define CH_15 (0x0e)
+#define CH_16 (0x0f)
+
+*/
+
+#endif /* _MIDICHANNELS_H_INCLUDED */
+
+
+
+
+// md5sum: 5267399f7ff90a6ea3ad2dc132afae3e - midichannels.h =css= 20030102
diff --git a/src/midiio/include/mididefines.h b/src/midiio/include/mididefines.h
new file mode 100644
index 0000000..4161c2f
--- /dev/null
+++ b/src/midiio/include/mididefines.h
@@ -0,0 +1,34 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Wed Feb 11 22:49:59 GMT-0800 1998
+// Filename: ...sig/code/control/misc/mididefines.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/mididefines.h
+// Syntax: C++
+//
+// Description: Collection of all of the MIDI convienience defines.
+//
+
+#ifndef _MIDIDEFINES_H_INCLUDED
+#define _MIDIDEFINES_H_INCLUDED
+
+
+// include channel defines
+#include "midichannels.h"
+
+
+// include note name defines
+#include "notenames.h"
+
+
+// include General MIDI instrument names
+#include "gminstruments.h"
+
+
+
+#endif /* _MIDIDEFINES_H_INCLUDED */
+
+
+
+
+// md5sum: 0f081c8e0b386a11e448b6088bfcd489 - mididefines.h =css= 20030102
diff --git a/src/midiio/include/midiiolib.h b/src/midiio/include/midiiolib.h
new file mode 100644
index 0000000..17d0430
--- /dev/null
+++ b/src/midiio/include/midiiolib.h
@@ -0,0 +1,57 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sat Nov 2 20:20:24 PST 2002
+// Last Modified: Thu Jan 2 18:51:20 PST 2003 (changed name from midio.h)
+// Filename: ...sig/code/misc/midiiolib.h
+// Web Address: http://sig.sapp.org/include/sig/midiiolib.h
+// Syntax: C++
+//
+// Description: Includes all of the header files for using the midiio
+// Library.
+//
+
+#ifndef _MIDIIOLIB_H_INCLUDED
+#define _MIDIIOLIB_H_INCLUDED
+
+#include "Array.h"
+#include "CircularBuffer.h"
+#include "Collection.h"
+#include "FileIO.h"
+#include "gminstruments.h"
+#include "midichannels.h"
+#include "mididefines.h"
+#include "MidiFile.h"
+#include "MidiFileWrite.h"
+#include "MidiInPort_alsa05.h"
+#include "MidiInPort_alsa.h"
+#include "MidiInPort.h"
+#include "MidiInPort_linux.h"
+#include "MidiInPort_oss.h"
+#include "MidiInPort_unsupported.h"
+#include "MidiInPort_visual.h"
+#include "MidiInput.h"
+#include "MidiIO.h"
+#include "MidiMessage.h"
+#include "MidiOutPort_alsa.h"
+#include "MidiOutPort.h"
+#include "MidiOutPort_linux.h"
+#include "MidiOutPort_oss.h"
+#include "MidiOutPort_unsupported.h"
+#include "MidiOutPort_visual.h"
+#include "MidiOutput.h"
+#include "MidiPort.h"
+#include "notenames.h"
+#include "Options.h"
+#include "Options_private.h"
+#include "Sequencer_alsa.h"
+#include "Sequencer_oss.h"
+#include "sigConfiguration.h"
+#include "SigTimer.h"
+#include "Voice.h"
+
+
+#endif /* _MIDIIO_H_INCLUDED */
+
+
+
+// md5sum: b389c20c620865344d827a88a0fb048d - midiiolib.h =css= 20030102
diff --git a/src/midiio/include/notenames.h b/src/midiio/include/notenames.h
new file mode 100644
index 0000000..ce9d505
--- /dev/null
+++ b/src/midiio/include/notenames.h
@@ -0,0 +1,219 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> (from 18Dec1997)
+// Creation Date: 26 December 1997
+// Last Modified: 26 December 1997
+// Filename: ...sig/code/control/misc/notenames.h
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/include/notenames.h
+// Syntax: C
+//
+// Description: Defines for pitch names of midi key numbers
+//
+
+#ifndef _NOTENAMES_H_INCLUDED
+#define _NOTENAMES_H_INCLUDED
+
+#define C00 (0)
+#define Cs00 (1)
+#define Db00 (1)
+#define D00 (2)
+#define Ds00 (3)
+#define Eb00 (3)
+#define E00 (4)
+#define F00 (5)
+#define Fs00 (6)
+#define Gb00 (6)
+#define G00 (7)
+#define Gs00 (8)
+#define Ab00 (8)
+#define A00 (9)
+#define As00 (10)
+#define Bb00 (10)
+#define B00 (11)
+
+#define C0 (12)
+#define Cs0 (13)
+#define Db0 (13)
+#define D0 (14)
+#define Ds0 (15)
+#define Eb0 (15)
+#define E0 (16)
+#define F0 (17)
+#define Fs0 (18)
+#define Gb0 (18)
+#define G0 (19)
+#define Gs0 (20)
+#define Ab0 (20)
+#define A0 (21)
+#define As0 (22)
+#define Bb0 (22)
+
+/*
+ * Note that the following symbol B0 is used in
+ * unix in the file /usr/include/termios.h also as
+ * a symbol, so It is disabled for now in this file.
+ * termios.h is need in Unix for the KeyboardInput.h file
+ */
+
+// #define B0 (23)
+
+#define C1 (24)
+#define Cs1 (25)
+#define Db1 (25)
+#define D1 (26)
+#define Ds1 (27)
+#define Eb1 (27)
+#define E1 (28)
+#define F1 (29)
+#define Fs1 (30)
+#define Gb1 (30)
+#define G1 (31)
+#define Gs1 (32)
+#define Ab1 (32)
+#define A1 (33)
+#define As1 (34)
+#define Bb1 (34)
+#define B1 (35)
+
+#define C2 (36)
+#define Cs2 (37)
+#define Db2 (37)
+#define D2 (38)
+#define Ds2 (39)
+#define Eb2 (39)
+#define E2 (40)
+#define F2 (41)
+#define Fs2 (42)
+#define Gb2 (42)
+#define G2 (43)
+#define Gs2 (44)
+#define Ab2 (44)
+#define A2 (45)
+#define As2 (46)
+#define Bb2 (46)
+#define B2 (47)
+
+#define C3 (48)
+#define Cs3 (49)
+#define Db3 (49)
+#define D3 (50)
+#define Ds3 (51)
+#define Eb3 (51)
+#define E3 (52)
+#define F3 (53)
+#define Fs3 (54)
+#define Gb3 (54)
+#define G3 (55)
+#define Gs3 (56)
+#define Ab3 (56)
+#define A3 (57)
+#define As3 (58)
+#define Bb3 (58)
+#define B3 (59)
+
+#define C4 (60)
+#define Cs4 (61)
+#define Db4 (61)
+#define D4 (62)
+#define Ds4 (63)
+#define Eb4 (63)
+#define E4 (64)
+#define F4 (65)
+#define Fs4 (66)
+#define Gb4 (66)
+#define G4 (67)
+#define Gs4 (68)
+#define Ab4 (68)
+#define A4 (69)
+#define As4 (70)
+#define Bb4 (70)
+#define B4 (71)
+
+#define C5 (72)
+#define Cs5 (73)
+#define Db5 (73)
+#define D5 (74)
+#define Ds5 (75)
+#define Eb5 (75)
+#define E5 (76)
+#define F5 (77)
+#define Fs5 (78)
+#define Gb5 (78)
+#define G5 (79)
+#define Gs5 (80)
+#define Ab5 (81)
+#define A5 (81)
+#define As5 (82)
+#define Bb5 (82)
+#define B5 (83)
+
+#define C6 (84)
+#define Cs6 (85)
+#define Db6 (85)
+#define D6 (86)
+#define Ds6 (87)
+#define Eb6 (87)
+#define E6 (88)
+#define F6 (89)
+#define Fs6 (90)
+#define Gb6 (90)
+#define G6 (91)
+#define Gs6 (92)
+#define Ab6 (92)
+#define A6 (93)
+#define As6 (94)
+#define Bb6 (94)
+#define B6 (95)
+
+#define C7 (96)
+#define Cs7 (97)
+#define Db7 (97)
+#define D7 (98)
+#define Ds7 (99)
+#define Eb7 (99)
+#define E7 (100)
+#define F7 (101)
+#define Fs7 (102)
+#define Gb7 (102)
+#define G7 (103)
+#define Gs7 (104)
+#define Ab7 (104)
+#define A7 (105)
+#define As7 (106)
+#define Bb7 (106)
+#define B7 (107)
+
+#define C8 (108)
+#define Cs8 (109)
+#define Db8 (109)
+#define D8 (110)
+#define Ds8 (111)
+#define Eb8 (111)
+#define E8 (112)
+#define F8 (113)
+#define Fs8 (114)
+#define Gb8 (114)
+#define G8 (115)
+#define Gs8 (116)
+#define Ab8 (116)
+#define A8 (117)
+#define As8 (118)
+#define Bb8 (118)
+#define B8 (119)
+
+#define C9 (120)
+#define Cs9 (121)
+#define Db9 (121)
+#define D9 (122)
+#define Ds9 (123)
+#define Eb9 (123)
+#define E9 (124)
+#define F9 (125)
+#define Fs9 (126)
+#define Gb9 (126)
+#define G9 (127)
+
+
+#endif /* _NOTENAMES_H_INCLUDED */
+
+
+// md5sum: c0f727163d32e04212a0ce5c8b6c4a6f - notenames.h =css= 20030102
diff --git a/src/midiio/include/sigConfiguration.h b/src/midiio/include/sigConfiguration.h
new file mode 100644
index 0000000..b1e5f17
--- /dev/null
+++ b/src/midiio/include/sigConfiguration.h
@@ -0,0 +1,100 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Dec 1 18:16:57 GMT-0800 1997
+// Last Modified: Mon Dec 1 18:16:57 GMT-0800 1997
+// Filename: ...sig/maint/code/misc/sigConfiguration.h
+// Web Address: http://sig.sapp.org/include/sig/sigConfiguration.h
+// Syntax: C
+//
+// Description: This file defines flags for different code setups:
+// You specify the OS in a compiler flag and this file takes care
+// of the rest of the defines for that OS. This file should
+// automatically be included in any file which uses any of the
+// define flags below.
+//
+// OS setup defines to use in compiling files:
+//
+// -DLINUX: Linux running on intel computers
+// -DNEXTI: NeXT OS on Intel Hardware
+// -DNEXTM: NeXT OS on Motorola Hardware
+// -DSUN: Sun SPARCstations
+// -DVISUAL: Windows 95/NT using Microsoft Visual C++ 5.0
+// -DHPUX: Hewlett-Packard Unix Workstations.
+// -DIRIX: SGI computers with IRIX OS.
+//
+//
+// Various options that can be defined for each OS. These
+// defines may be mixed and matched in different OSes:
+//
+// -DOTHEREND: If the computer is little-endian, then this
+// define switches the byte ordering behavior for writing/reading
+// soundfiles. Intel computers need this define, most others
+// will not.need this define.
+//
+// -DSHORTRAND: Indicates that the rand() function generates
+// numbers between 0 and 0x7fff. The default without this
+// option is a range between 0 and 0x7fffffff.
+//
+// -DINTEL: Indicates that the computer hardware uses an
+// intel x86 CPU. Not used for anything right now except to
+// define the endian flag (OTHEREND).
+//
+// -DMOTOROLA: Indicates that the computer hardware uses a
+// Motorola 68k CPU. Not used for anything right now.
+//
+//
+
+#ifndef _SIGCONFIGURATION_H_INCLUDED
+#define _SIGCONFIGURATION_H_INCLUDED
+
+
+#ifdef LINUX
+ #define INTEL
+#endif
+
+
+#ifdef NEXTI
+ #define INTEL
+#endif
+
+
+#ifdef NEXT
+ #define MOTOROLA
+#endif
+
+
+#ifdef VISUAL
+ #define INTEL
+#endif
+
+
+#ifdef SUN
+ #define SHORTRAND
+#endif
+
+
+#ifdef HPUX
+ #define SHORTRAND
+#endif
+
+
+#ifdef IRIX
+ #define SHORTRAND
+#endif
+
+
+// These defines must come after the previous defines:
+
+
+#ifdef INTEL
+ #define OTHEREND
+#endif
+
+
+
+#endif /* _SIGCONFIGURATION_H_INCLUDED */
+
+
+
+// md5sum: 32f74a7c264b158b83ff38db1ea885f8 - sigConfiguration.h =css= 20030102
diff --git a/src/midiio/src/FileIO.cpp b/src/midiio/src/FileIO.cpp
new file mode 100644
index 0000000..93ef153
--- /dev/null
+++ b/src/midiio/src/FileIO.cpp
@@ -0,0 +1,761 @@
+//
+// Copyright 1997 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri May 9 22:30:32 PDT 1997
+// Last Modified: Sun Dec 14 03:29:39 GMT-0800 1997
+// Filename: ...sig/maint/code/sigBase/FileIO.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/FileIO.cpp
+// Documentation: http://sig.sapp.org/doc/classes/FileIO
+// Syntax: C++
+//
+// Description: Derived from the fstream class, this class has
+// functions which allow writing binary files in
+// both little and big endian formats. Useful for
+// writing files such as soundfiles and MIDI files
+// which require numbers to be stored in a particular
+// endian format.
+//
+
+#include "FileIO.h"
+#include "sigConfiguration.h"
+
+//////////////////////////////
+//
+// FileIO::FileIO --
+//
+
+FileIO::FileIO(void) {
+ // do nothing
+};
+
+FileIO::FileIO(const char* filename, std::ios::openmode state) :
+#ifdef VISUAL /* for stupid LF-CR prevention in DOS */
+ std::fstream(filename, state | ios::binary) {
+#else
+ std::fstream(filename, state) {
+#endif
+ // do nothing
+};
+
+
+
+//////////////////////////////
+//
+// FileIO::~FileIO --
+//
+
+FileIO::~FileIO() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readBigEndian --
+// Read numbers from a file as big endian
+//
+
+void FileIO::readBigEndian(char& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(uchar& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(short& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(ushort& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(long& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(ulong& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(int& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(uint& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(float& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readBigEndian(double& aNumber) {
+ #ifdef OTHEREND
+ readNotMachineEndian(aNumber);
+ #else
+ readMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readLittleEndian --
+// Read numbers from a file as little endian
+//
+
+void FileIO::readLittleEndian(char& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(uchar& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(short& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(ushort& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(long& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(ulong& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(int& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(uint& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(float& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::readLittleEndian(double& aNumber) {
+ #ifdef OTHEREND
+ readMachineEndian(aNumber);
+ #else
+ readNotMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readMachineEndian --
+// Read numbers from a file in the same endian as the computer.
+//
+
+void FileIO::readMachineEndian(char& aNumber) {
+ this->read(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(uchar& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(short& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(ushort& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(long& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(ulong& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(int& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(uint& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(float& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::readMachineEndian(double& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::readNotMachineEndian --
+// Read numbers from a file with different endian from the computer.
+//
+
+void FileIO::readNotMachineEndian(char& aNumber) {
+ this->read(&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(uchar& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(short& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(ushort& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(long& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(ulong& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(int& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(uint& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(float& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+void FileIO::readNotMachineEndian(double& aNumber) {
+ this->read((char*)&aNumber, sizeof(aNumber));
+ aNumber = flipBytes(aNumber);
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeBigEndian --
+//
+
+void FileIO::writeBigEndian(char aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(uchar aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(short aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(ushort aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(long aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(ulong aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(int aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(uint aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(float aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeBigEndian(double aNumber) {
+ #ifdef OTHEREND
+ writeNotMachineEndian(aNumber);
+ #else
+ writeMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeLittleEndian --
+//
+
+void FileIO::writeLittleEndian(char aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(uchar aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(short aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(ushort aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(long aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(ulong aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(int aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(uint aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(float aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+void FileIO::writeLittleEndian(double aNumber) {
+ #ifdef OTHEREND
+ writeMachineEndian(aNumber);
+ #else
+ writeNotMachineEndian(aNumber);
+ #endif
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeMachineEndian --
+//
+
+void FileIO::writeMachineEndian(char aNumber) {
+ this->write(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(uchar aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(short aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(ushort aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(long aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(ulong aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(int aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(uint aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(float aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeMachineEndian(double aNumber) {
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+
+
+//////////////////////////////
+//
+// FileIO::writeNotMachineEndian --
+//
+
+void FileIO::writeNotMachineEndian(char aNumber) {
+ // aNumber = flipBytes(aNumber);
+ this->write(&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(uchar aNumber) {
+ // aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(short aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(ushort aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(long aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(ulong aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(int aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(uint aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(float aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+void FileIO::writeNotMachineEndian(double aNumber) {
+ aNumber = flipBytes(aNumber);
+ this->write((char*)&aNumber, sizeof(aNumber));
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// flipBytes -- flip the bytes in a number
+//
+
+char FileIO::flipBytes(char aNumber) {
+ return aNumber;
+}
+
+
+uchar FileIO::flipBytes(uchar aNumber) {
+ return aNumber;
+}
+
+
+short FileIO::flipBytes(short aNumber) {
+ static uchar output[2];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[1];
+ output[1] = input[0];
+
+ return *((short*)(&output));
+}
+
+
+ushort FileIO::flipBytes(ushort aNumber) {
+ static uchar output[2];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[1];
+ output[1] = input[0];
+
+ return *((ushort*)(&output));
+}
+
+
+long FileIO::flipBytes(long aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((long*)(&output));
+}
+
+
+ulong FileIO::flipBytes(ulong aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((ulong*)(&output));
+}
+
+
+int FileIO::flipBytes(int aNumber) {
+ static uchar output[sizeof(uint)];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ for(uint i=0; i<sizeof(int); i++) {
+ output[i] = input[sizeof(int)-1-i];
+ }
+
+ return *((int*)(&output));
+}
+
+
+uint FileIO::flipBytes(uint aNumber) {
+ static uchar output[sizeof(uint)];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ for(uint i=0; i<sizeof(uint); i++) {
+ output[i] = input[sizeof(uint)-1-i];
+ }
+
+ return *((uint*)(&output));
+}
+
+
+
+float FileIO::flipBytes(float aNumber) {
+ static uchar output[4];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[3];
+ output[1] = input[2];
+ output[2] = input[1];
+ output[3] = input[0];
+
+ return *((float*)(&output));
+}
+
+
+double FileIO::flipBytes(double aNumber) {
+ static uchar output[8];
+ static uchar* input;
+ input = (uchar*)(&aNumber);
+
+ output[0] = input[7];
+ output[1] = input[6];
+ output[2] = input[5];
+ output[3] = input[4];
+ output[4] = input[3];
+ output[5] = input[2];
+ output[6] = input[1];
+ output[7] = input[0];
+
+ return *((double*)(&output));
+}
+
+
+
+/* This is what I want to use
+template<class type>
+type FileIO::flipBytes(type aThing) {
+ uchar* input = (uchar*)(&aNumber);
+ uchar output[sizeof(aThing)];
+
+ for(int i=0; i<sizeof(aThing); i++) {
+ output[i] = input[sizeof(aThing) - 1 - i];
+ }
+
+ return *((type*)(&output));
+}
+*/
+
+
+
+// md5sum: a82bcb961043a48d2cae34d5eaac0101 - FileIO.cpp =css= 20030102
diff --git a/src/midiio/src/MidiFile.cpp b/src/midiio/src/MidiFile.cpp
new file mode 100644
index 0000000..e3307ca
--- /dev/null
+++ b/src/midiio/src/MidiFile.cpp
@@ -0,0 +1,1200 @@
+//
+// Copyright 1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Nov 26 14:12:01 PST 1999
+// Last Modified: Fri Dec 2 13:26:29 PST 1999
+// Last Modified: Wed Dec 13 10:33:30 PST 2000 (modified sorting routine)
+// Last Modified: Tue Jan 22 23:23:37 PST 2002 (allowed reading of meta events)
+// Filename: ...sig/src/sigInfo/MidiFile.cpp
+// Web Address: http://sig.sapp.org/src/sigInfo/MidiFile.cpp
+// Syntax: C++
+//
+// Description: A class which can read/write Standard MIDI files.
+// MIDI data is stored by track in an array. This
+// class is used for example in the MidiPerform class.
+//
+
+#include "MidiFile.h"
+#include <iomanip>
+
+//////////////////////////////
+//
+// _MFEvent::_MFEvent --
+//
+
+_MFEvent::_MFEvent(void) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(0);
+}
+
+_MFEvent::_MFEvent(int command) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(1);
+ data[0] = (uchar)command;
+}
+
+_MFEvent::_MFEvent(int command, int param1) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(2);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+}
+
+_MFEvent::_MFEvent(int command, int param1, int param2) {
+ time = 0;
+ track = 0;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+_MFEvent::_MFEvent(int aTrack, int command, int param1, int param2) {
+ time = 0;
+ track = aTrack;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+_MFEvent::_MFEvent(int aTime, int aTrack, int command, int param1, int param2) {
+ time = aTime;
+ track = aTrack;
+ data.allowGrowth();
+ data.setSize(3);
+ data[0] = (uchar)command;
+ data[1] = (uchar)param1;
+ data[2] = (uchar)param2;
+}
+
+
+
+//////////////////////////////
+//
+// _MFEvent::~MFEvent
+//
+
+_MFEvent::~_MFEvent() {
+ time = -1;
+ track = -1;
+ data.setSize(0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::MidiFile --
+//
+
+MidiFile::MidiFile(void) {
+ ticksPerQuarterNote = 48; // time base of file
+ trackCount = 1; // # of tracks in file
+ theTrackState = TRACK_STATE_SPLIT; // joined or split
+ theTimeState = TIME_STATE_DELTA; // absolute or delta
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+ readFileName = new char[1];
+ readFileName[0] = '\0';
+}
+
+
+MidiFile::MidiFile(char* aFile) {
+ ticksPerQuarterNote = 48; // time base of file
+ trackCount = 1; // # of tracks in file
+ theTrackState = TRACK_STATE_SPLIT; // joined or split
+ theTimeState = TIME_STATE_DELTA; // absolute or delta
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+ readFileName = new char[1];
+ readFileName[0] = '\0';
+ read(aFile);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::~MidiFile --
+//
+
+MidiFile::~MidiFile() {
+ if (readFileName != NULL) {
+ delete [] readFileName;
+ readFileName = NULL;
+ }
+
+ erase();
+
+ if (events[0] != NULL) {
+ delete events[0];
+ events[0] = NULL;
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::absoluteTime -- convert the time data to
+// absolute time, which means that the time field
+// in the _MFEvent struct represents the exact tick
+// time to play the event rather than the time since
+// the last event to wait untill playing the current
+// event.
+//
+
+void MidiFile::absoluteTime(void) {
+ if (getTimeState() == TIME_STATE_ABSOLUTE) {
+ return;
+ }
+ int i, j;
+ int length = getNumTracks();
+ int* timedata = new int[length];
+ for (i=0; i<length; i++) {
+ timedata[i] = 0;
+ if (events[i]->getSize() > 0) {
+ timedata[i] = (*events[i])[0].time;
+ } else {
+ continue;
+ }
+ for (j=1; j<events[i]->getSize(); j++) {
+ timedata[i] += (*events[i])[j].time;
+ (*events[i])[j].time = timedata[i];
+ }
+ }
+ theTimeState = TIME_STATE_ABSOLUTE;
+ delete [] timedata;
+}
+
+//////////////////////////////
+//
+// MidiFile::addEvent --
+//
+
+int MidiFile::addEvent(int aTrack, int aTime, Array<uchar>& midiData) {
+ _MFEvent anEvent;
+ anEvent.time = aTime;
+ anEvent.track = aTrack;
+ anEvent.data = midiData;
+
+ events[aTrack]->append(anEvent);
+ return events[aTrack]->getSize() - 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::addTrack -- adds a blank track at end of the
+// track list. Returns the track number of the added
+// track.
+//
+
+int MidiFile::addTrack(void) {
+ int length = getNumTracks();
+ events.setSize(length+1);
+ events[length] = new Collection<_MFEvent>;
+ events[length]->setSize(10000);
+ events[length]->setSize(0);
+ events[length]->allowGrowth(1);
+ return length;
+}
+
+int MidiFile::addTrack(int count) {
+ int length = getNumTracks();
+ events.setSize(length+count);
+ int i;
+ for (i=0; i<count; i++) {
+ events[length + i] = new Collection<_MFEvent>;
+ events[length + i]->setSize(10000);
+ events[length + i]->setSize(0);
+ events[length + i]->allowGrowth(1);
+ }
+ return length + count - 1;
+}
+
+
+//////////////////////////////
+//
+// MidiFile::allocateEvents --
+//
+
+void MidiFile::allocateEvents(int track, int aSize) {
+ int oldsize = events[track]->getSize();
+ if (oldsize < aSize) {
+ events[track]->setSize(aSize);
+ events[track]->setSize(oldsize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::deleteTrack -- remove a track from the MidiFile.
+// Tracks are numbered starting at track 0.
+//
+
+void MidiFile::deleteTrack(int aTrack) {
+ int length = getNumTracks();
+ if (aTrack < 0 || aTrack >= length) {
+ return;
+ }
+ if (length == 1) {
+ return;
+ }
+ delete events[aTrack];
+ for (int i=aTrack; i<length-1; i++) {
+ events[i] = events[i+1];
+ }
+
+ events[length] = NULL;
+ events.setSize(length-1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::deltaTime -- convert the time data to
+// delta time, which means that the time field
+// in the _MFEvent struct represents the time
+// since the last event was played. When a MIDI file
+// is read from a file, this is the default setting.
+//
+
+void MidiFile::deltaTime(void) {
+ if (getTimeState() == TIME_STATE_DELTA) {
+ return;
+ }
+ int i, j;
+ int temp;
+ int length = getNumTracks();
+ int *timedata = new int[length];
+ for (i=0; i<length; i++) {
+ timedata[i] = 0;
+ if (events[i]->getSize() > 0) {
+ timedata[i] = (*events[i])[0].time;
+ } else {
+ continue;
+ }
+ for (j=1; j<events[i]->getSize(); j++) {
+ temp = (*events[i])[j].time;
+ (*events[i])[j].time = temp - timedata[i];
+ timedata[i] = temp;
+ }
+ }
+ theTimeState = TIME_STATE_DELTA;
+ delete [] timedata;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::erase -- make the MIDI file empty with one
+// track with no data in it.
+//
+
+void MidiFile::erase(void) {
+ int length = getNumTracks();
+ for (int i=0; i<length; i++) {
+ delete events[i];
+ events[i] = NULL;
+ }
+ events.setSize(1);
+ events[0] = new Collection<_MFEvent>;
+ events[0]->setSize(0);
+ events[0]->allowGrowth(1);
+}
+
+
+void MidiFile::clear(void) {
+ MidiFile::erase();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getEvent -- return the event at the given index in the
+// specified track.
+//
+
+_MFEvent& MidiFile::getEvent(int aTrack, int anIndex) {
+ return (*events[aTrack])[anIndex];
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTicksPerQuarterNote -- returns the number of
+// time units that are supposed to occur during a quarternote.
+//
+
+int MidiFile::getTicksPerQuarterNote(void) {
+ return ticksPerQuarterNote;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTrackCount -- return the number of tracks in
+// the Midi File.
+//
+
+int MidiFile::getTrackCount(void) {
+ return events.getSize();
+}
+
+int MidiFile::getNumTracks(void) {
+ return events.getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getNumEvents -- returns the number of events
+// in a given track.
+//
+
+int MidiFile::getNumEvents(int aTrack) {
+ return events[aTrack]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::joinTracks -- merge the data from all tracks,
+// but keeping the identity of the tracks unique so that
+// the function splitTracks can be called to split the
+// tracks into separate units again. The style of the
+// MidiFile when read from a file is with tracks split.
+//
+
+void MidiFile::joinTracks(void) {
+ if (getTrackState() == TRACK_STATE_JOINED) {
+ return;
+ }
+ if (getNumTracks() == 1) {
+ return;
+ }
+
+ Collection <_MFEvent>* joinedTrack;
+ joinedTrack = new Collection<_MFEvent>;
+ joinedTrack->setSize(200000);
+ joinedTrack->setSize(0);
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+ int i, j;
+ int length = getNumTracks();
+ for (i=0; i<length; i++) {
+ for (j=0; j<events[i]->getSize(); j++) {
+ joinedTrack->append((*events[i])[j]);
+ }
+ }
+
+ erase();
+
+ delete events[0];
+ events[0] = joinedTrack;
+ sortTracks();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::mergeTracks -- combine the data from two
+// tracks into one. Placing the data in the first
+// track location listed, and Moving the other tracks
+// in the file around to fill in the spot where Track2
+// used to be. The results of this function call cannot
+// be reversed.
+//
+
+void MidiFile::mergeTracks(int aTrack1, int aTrack2) {
+ Collection <_MFEvent>* mergedTrack;
+ mergedTrack = new Collection<_MFEvent>;
+ mergedTrack->setSize(0);
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+ int i, j;
+ int length = getNumTracks();
+ for (i=0; i<events[aTrack1]->getSize(); i++) {
+ mergedTrack->append((*events[aTrack1])[i]);
+ }
+ for (j=0; j<events[aTrack2]->getSize(); i++) {
+ (*events[aTrack2])[i].track = aTrack1;
+ mergedTrack->append((*events[aTrack2])[i]);
+ }
+
+ sortTrack(*mergedTrack);
+
+ delete events[aTrack1];
+
+ events[aTrack1] = mergedTrack;
+
+ for (i=aTrack2; i<length-1; i++) {
+ events[i] = events[i+1];
+ }
+
+ events[length] = NULL;
+ events.setSize(length-1);
+
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::read -- read a MIDI file and store its contents.
+//
+
+int MidiFile::read(char* aFile) {
+
+ #ifdef VISUAL
+ FileIO inputfile(aFile, std::ios::in | std::ios::nocreate | std::ios::binary);
+ #else
+ // ios::nocreate does not exists anymore in GCC 3.x
+ FileIO inputfile(aFile, std::ios::in /*| std::ios::nocreate */);
+ #endif
+
+ if (!inputfile.is_open()) {
+ return 0;
+ }
+
+ // Read the MIDI header (4 bytes of ID, 4 byte data size, 6 bytes
+ // of data.
+
+ ulong longdata;
+ uchar chardata;
+ ushort shortdata;
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'M') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ std::cout << "Chara data is" << chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'T') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'h') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'd') {
+ std::cout << "File: " << aFile << " is not a MIDI file" << std::endl;
+ return 0;
+ }
+
+ // read header size
+ inputfile.readBigEndian(longdata);
+ if (longdata != 6) {
+ std::cout << "File: " << aFile
+ << " is not a MIDI 1.0 Standard MIDI file." << std::endl;
+ std::cout << "The header size is: " << longdata << std::endl;
+ return 0;
+ }
+
+ // read file type
+ int type;
+ inputfile.readBigEndian(shortdata);
+ switch (shortdata) {
+ case 0:
+ type = 0;
+ break;
+ case 1:
+ type = 1;
+ break;
+ default:
+ std::cout << "Error: cannot handle type " << shortdata
+ << " MIDI file" << std::endl;
+ return 0;
+ }
+
+ // read number of tracks
+ int tracks;
+ inputfile.readBigEndian(shortdata);
+ if (type == 0 && shortdata != 1) {
+ std::cout << "Error: Type 0 MIDI file can only contain one track" << std::endl;
+ return 0;
+ } else {
+ tracks = shortdata;
+ }
+ // std::cout << "Track count is: " << tracks << std::endl;
+ erase();
+ if (events[0] != NULL) {
+ delete events[0];
+ }
+ events.setSize(tracks);
+ for (int z=0; z<tracks; z++) {
+ events[z] = new Collection<_MFEvent>;
+ events[z]->setAllocSize(10000);
+ events[z]->setSize(0);
+ events[z]->allowGrowth(1);
+ }
+
+ // read ticks per quarter note
+ short signeddata;
+ inputfile.readBigEndian(signeddata);
+ if (signeddata <= 0) {
+ std::cout << "Error: cannot handle SMTP tick values for quarter notes"
+ " yet" << std::endl;
+ return 0;
+ }
+ ticksPerQuarterNote = signeddata;
+
+ //////////////////////////////////////////////////
+ //
+ // now read individual tracks:
+ //
+
+ uchar runningCommand = 0;
+ _MFEvent event;
+ int absticks;
+ int barline;
+
+ for (int i=0; i<tracks; i++) {
+ // std::cout << "\nReading Track: " << i + 1 << flush;
+ // read track header...
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'M') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 1 is: " << (int)chardata << std::endl;
+ inputfile.readBigEndian(chardata);
+ if (inputfile.eof()) {
+ std::cout << "End of file reached" << std::endl;
+ }
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'T') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 2 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'r') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 3 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ inputfile.readBigEndian(chardata);
+ if (chardata != 'k') {
+ std::cout << "File: " << aFile << " has bad track info" << std::endl;
+ std::cout << "character 4 is: " << (int)chardata << std::endl;
+ return 0;
+ }
+
+ // Now read track chunk size and throw it away because it is
+ // not really necessary since the track MUST end with an
+ // end of track meta event, and 50% of Midi files or so
+ // do not correctly give the track size.
+ inputfile.readBigEndian(longdata);
+
+ // set the size of the track allocation so that it might
+ // approximately fit the data.
+ events[i]->setSize(longdata/2);
+ events[i]->setSize(0);
+
+ // process the track
+ absticks = 0;
+ barline = 1;
+ while (!inputfile.eof()) {
+ longdata = extractVlvTime(inputfile);
+//std::cout << "ticks = " << longdata << std::endl;
+ absticks += longdata;
+ extractMidiData(inputfile, event.data, runningCommand);
+//std::cout << "command = " << std::hex << (int)event.data[0] << std::dec << std::endl;
+ if (event.data[0] == 0xff && (event.data[1] == 1 ||
+ event.data[1] == 2 || event.data[1] == 3 || event.data[1] == 4)) {
+ // mididata.append('\0');
+ // std::cout << '\t';
+ // for (int m=0; m<event.data[2]; m++) {
+ // std::cout << event.data[m+3];
+ // }
+ // std::cout.flush();
+ } else if (event.data[0] == 0xff && event.data[1] == 0x2f) {
+ break;
+ }
+
+ if (event.data[0] != 0xff && event.data[0] != 0xf0) {
+ event.time = absticks;
+ if ((event.data[0] & 0xf0) == 0x90) {
+ if (event.data[1] < 12) {
+ event.data[0] = event.data[1];
+ switch (event.data[0]) {
+ case 2: event.data[2] = barline++; // barline
+ break;
+ case 0: break; // beat
+ }
+ }
+ }
+ event.track = i;
+ events[i]->append(event);
+ } else {
+ event.time = absticks;
+ event.track = i;
+ events[i]->append(event);
+ }
+
+ }
+
+ }
+ // std::cout << std::endl;
+
+ theTimeState = TIME_STATE_ABSOLUTE;
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::setTicksPerQuarterNote --
+//
+
+void MidiFile::setTicksPerQuarterNote(int ticks) {
+ ticksPerQuarterNote = ticks;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::sortTrack --
+//
+
+void MidiFile::sortTrack(Collection<_MFEvent>& trackData) {
+ qsort(trackData.getBase(), trackData.getSize(),
+ sizeof(_MFEvent), eventcompare);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::sortTracks -- sort all tracks in the MidiFile.
+//
+
+void MidiFile::sortTracks(void) {
+ for (int i=0; i<getTrackCount(); i++) {
+ sortTrack(*events[i]);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::splitTracks -- take the joined tracks and split them
+// back into their separate track identities.
+//
+
+void MidiFile::splitTracks(void) {
+ if (getTrackState() == TRACK_STATE_SPLIT) {
+ return;
+ }
+
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_DELTA) {
+ absoluteTime();
+ }
+
+ int maxTrack = 0;
+ int i;
+ int length = events[0]->getSize();
+ for (i=0; i<length; i++) {
+ if ((*events[0])[i].track > maxTrack) {
+ maxTrack = (*events[0])[i].track;
+ }
+ }
+
+ Collection<_MFEvent>* olddata = events[0];
+ events[0] = NULL;
+ events.setSize(maxTrack);
+ for (i=0; i<maxTrack; i++) {
+ events[i] = new Collection<_MFEvent>;
+ events[i]->setSize(0);
+ events[i]->allowGrowth();
+ }
+
+ int trackValue = 0;
+ for (i=0; length; i++) {
+ trackValue = (*olddata)[i].track;
+ events[trackValue]->append((*olddata)[i]);
+ }
+
+ delete olddata;
+
+ if (oldTimeState == TIME_STATE_DELTA) {
+ deltaTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::timeState -- returns what type of time method is
+// being used: either TIME_STATE_ABSOLUTE or TIME_STATE_DELTA.
+//
+
+int MidiFile::getTimeState(void) {
+ return theTimeState;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::getTrackState -- returns what type of track method
+// is being used: either TRACK_STATE_JOINED or TRACK_STATE_SPLIT.
+//
+
+int MidiFile::getTrackState(void) {
+ return theTrackState;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFile::write -- write a standard MIDI file from data.
+//
+
+int MidiFile::write(const char* aFile) {
+ int oldTimeState = getTimeState();
+ if (oldTimeState == TIME_STATE_ABSOLUTE) {
+ deltaTime();
+ }
+
+ #ifdef VISUAL
+ FileIO outputfile(aFile, ios::out | ios::noreplace | ios::binary);
+ #else
+ // ios::noreplace does not exists anymore in GCC 3.x
+ FileIO outputfile(aFile, std::ios::out /* | std::ios::noreplace */);
+ #endif
+
+ if (!outputfile.is_open()) {
+ std::cout << "Error: could not write: " << aFile << std::endl;
+ exit(1);
+ }
+
+ // write the header of the Standard MIDI File
+
+ char ch;
+ // 1. The characters "MThd"
+ ch = 'M';
+ outputfile.writeBigEndian(ch);
+ ch = 'T';
+ outputfile.writeBigEndian(ch);
+ ch = 'h';
+ outputfile.writeBigEndian(ch);
+ ch = 'd';
+ outputfile.writeBigEndian(ch);
+
+ // 2. write the size of the header (alwas a "6" stored in unsigned long
+ ulong longdata = 6;
+ outputfile.writeBigEndian(longdata);
+
+ // 3. MIDI file format, type 0, 1, or 2
+ ushort shortdata;
+ if (getNumTracks() == 1) {
+ shortdata = 0;
+ } else {
+ shortdata = 1;
+ }
+ outputfile.writeBigEndian(shortdata);
+
+ // 4. write out the number of tracks.
+ shortdata = getNumTracks();
+ outputfile.writeBigEndian(shortdata);
+
+ // 5. write out the number of ticks per quarternote. (avoiding SMTPE for now)
+ shortdata = getTicksPerQuarterNote();
+ outputfile.writeBigEndian(shortdata);
+
+ // now write each track.
+ Array<uchar> trackdata;
+ uchar endoftrack[4] = {0, 0xff, 0x2f, 0x00};
+ int i, j, k;
+ int size;
+ for (i=0; i<getNumTracks(); i++) {
+ trackdata.setSize(1000000); // make the track data larger than
+ // expected data input
+ trackdata.setGrowth(1000000);
+ trackdata.setSize(0);
+ trackdata.allowGrowth();
+ for (j=0; j<events[i]->getSize(); j++) {
+ writeVLValue((*events[i])[j].time, trackdata);
+ for (k=0; k<(*events[i])[j].data.getSize(); k++) {
+ trackdata.append((*events[i])[j].data[k]);
+ }
+ }
+ size = trackdata.getSize();
+ if ((trackdata[size-3] != 0xff) && (trackdata[size-2] != 0x2f)) {
+ trackdata.append(endoftrack[0]);
+ trackdata.append(endoftrack[1]);
+ trackdata.append(endoftrack[2]);
+ trackdata.append(endoftrack[3]);
+ }
+
+ // now ready to write to MIDI file.
+
+ // first write the track ID marker "MTrk":
+ ch = 'M';
+ outputfile.writeBigEndian(ch);
+ ch = 'T';
+ outputfile.writeBigEndian(ch);
+ ch = 'r';
+ outputfile.writeBigEndian(ch);
+ ch = 'k';
+ outputfile.writeBigEndian(ch);
+
+ // A. write the size of the MIDI data to follow:
+ longdata = trackdata.getSize();
+ outputfile.writeBigEndian(longdata);
+
+ // B. write the actual data
+ outputfile.write((char*)trackdata.getBase(), trackdata.getSize());
+ }
+
+ if (oldTimeState == TIME_STATE_ABSOLUTE) {
+ absoluteTime();
+ }
+
+ outputfile.close();
+
+ return 1;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// MidiF::extractMidiData --
+//
+
+void MidiFile::extractMidiData(FileIO& inputfile, Array<uchar>& array,
+ uchar& runningCommand) {
+
+ uchar byte;
+ array.setSize(0);
+ array.allowGrowth();
+ int runningQ;
+
+ inputfile.readBigEndian(byte);
+
+ if (byte < 0x80) {
+ runningQ = 1;
+ if (runningCommand == 0) {
+ std::cout << "Error: running command with no previous command" << std::endl;
+ exit(1);
+ }
+ } else {
+ runningCommand = byte;
+ runningQ = 0;
+ }
+
+ array.append(runningCommand);
+ if (runningQ) {
+ array.append(byte);
+ }
+
+ uchar metai;
+ switch (runningCommand & 0xf0) {
+ case 0x80: // note off (2 more bytes)
+ case 0x90: // note on (2 more bytes)
+ case 0xA0: // aftertouch (2 more bytes)
+ case 0xB0: // cont. controller (2 more bytes)
+ case 0xE0: // pitch wheel (2 more bytes)
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ if (!runningQ) {
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ }
+ break;
+ case 0xC0: // patch change (1 more byte)
+ case 0xD0: // channel pressure (1 more byte)
+ if (!runningQ) {
+ inputfile.readBigEndian(byte);
+ array.append(byte);
+ }
+ break;
+ case 0xF0:
+ switch (runningCommand) {
+ case 0xff: // meta event
+ {
+ if (!runningQ) {
+ inputfile.readBigEndian(byte); // meta type
+ array.append(byte);
+ }
+ inputfile.readBigEndian(metai); // meta size
+ array.append(metai);
+ for (uchar j=0; j<metai; j++) {
+ inputfile.readBigEndian(byte); // meta data
+ array.append(byte);
+ }
+ }
+ break;
+ case 0xf0: // sysex
+ // read until you find a 0xf7 character
+ byte = 0;
+ while (byte != 0xf7 && !inputfile.eof()) {
+ inputfile.readBigEndian(byte); // meta data
+ }
+ break;
+ }
+ break;
+ default:
+ std::cout << "Error reading midifile" << std::endl;
+ std::cout << "Command byte was " << (int)runningCommand << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiF::extractVlvTime --
+//
+
+ulong MidiFile::extractVlvTime(FileIO& inputfile) {
+ uchar b[5] = {0};
+
+ for (int i=0; i<5; i++) {
+ inputfile.readBigEndian(b[i]);
+ if (b[i] < 0x80) {
+ break;
+ }
+ }
+
+ return unpackVLV(b[0], b[1], b[2], b[3], b[4]);
+}
+
+
+
+//////////////////////////////
+//
+// MidiF::unpackVLV -- converts a VLV value to pure unsigned long value.
+// default values: a = b = c = d = e = 0;
+//
+
+ulong MidiFile::unpackVLV(uchar a, uchar b, uchar c, uchar d, uchar e) {
+ if (e > 0x7f) {
+ std::cout << "Error: VLV value was too long" << std::endl;
+ exit(1);
+ }
+
+ uchar bytes[5] = {a, b, c, d, e};
+ int count = 0;
+ while (bytes[count] > 0x7f && count < 5) {
+ count++;
+ }
+ count++;
+
+ ulong output = 0;
+ for (int i=0; i<count; i++) {
+ output = output << 7;
+ output = output | (bytes[i] & 0x7f);
+ }
+
+ return output;
+}
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeVLValue -- write a number to the midifile
+// as a variable length value which segments a file into 7-bit
+// values. Maximum size of aValue is 0x7fffffff
+//
+
+void MidiFile::writeVLValue(long aValue, Array<uchar>& outdata) {
+ uchar bytes[5] = {0};
+ bytes[0] = (uchar)(((ulong)aValue >> 28) & 0x7f); // most significant 5 bits
+ bytes[1] = (uchar)(((ulong)aValue >> 21) & 0x7f); // next largest 7 bits
+ bytes[2] = (uchar)(((ulong)aValue >> 14) & 0x7f);
+ bytes[3] = (uchar)(((ulong)aValue >> 7) & 0x7f);
+ bytes[4] = (uchar)(((ulong)aValue) & 0x7f); // least significant 7 bits
+
+ int start = 0;
+ while (start<5 && bytes[start] == 0) start++;
+
+ for (int i=start; i<4; i++) {
+ bytes[i] = bytes[i] | 0x80;
+ outdata.append(bytes[i]);
+ }
+ outdata.append(bytes[4]);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// external functions
+//
+
+
+//////////////////////////////
+//
+// eventcompare -- for sorting the tracks
+//
+
+int eventcompare(const void* a, const void* b) {
+ _MFEvent& aevent = *((_MFEvent*)a);
+ _MFEvent& bevent = *((_MFEvent*)b);
+
+ if (aevent.time > bevent.time) {
+ return 1;
+ } else if (aevent.time < bevent.time) {
+ return -1;
+ } else if (aevent.data[0] == 0xff && bevent.data[0] != 0xff) {
+ return 1;
+ } else if (bevent.data[0] == 0xff && aevent.data[0] != 0xff) {
+ return -1;
+ } else if (bevent.data[0] == 0xff && bevent.data[1] == 0x2f) {
+ return -1;
+ } else if (aevent.data[0] == 0xff && aevent.data[1] == 0x2f) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// operator<< -- for printing an ASCII version of the MIDI file
+//
+
+std::ostream& operator<<(std::ostream& out, MidiFile& aMidiFile) {
+ int i, j, k;
+ out << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
+ out << "Number of Tracks: " << aMidiFile.getTrackCount() << "\n";
+ out << "Time method: " << aMidiFile.getTimeState();
+ if (aMidiFile.getTimeState() == TIME_STATE_DELTA) {
+ out << " (Delta timing)";
+ } else if (aMidiFile.getTimeState() == TIME_STATE_ABSOLUTE) {
+ out << " (Absolute timing)";
+ } else {
+ out << " (unknown method)";
+ }
+ out << "\n";
+
+ out << "Divisions per Quarter Note: " << std::dec << aMidiFile.getTicksPerQuarterNote() << "\n";
+ for (i=0; i<aMidiFile.getNumTracks(); i++) {
+ out << "\nTrack " << i
+ << " +++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";
+ for (j=0; j<aMidiFile.getNumEvents(i); j++) {
+ out << std::dec << aMidiFile.getEvent(i, j).time << "\t"
+ << "0x" << std::hex << (int)aMidiFile.getEvent(i, j).data[0] << " ";
+ if (aMidiFile.getEvent(i, j).data[0] == 0xff) {
+
+ if (aMidiFile.getEvent(i, j).data[1] == 0x01) {
+ out << "TEXT [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x02) {
+ out << "COPY [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x03) {
+ out << "TRACK [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x04) {
+ out << "INSTR [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else if (aMidiFile.getEvent(i, j).data[1] == 0x05) {
+ out << "LYRIC [";
+ for (k=3; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << (char)aMidiFile.getEvent(i, j).data[k];
+ }
+ out << "]";
+
+ } else {
+ for (k=1; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << std::dec << (int)aMidiFile.getEvent(i, j).data[k] << " ";
+ }
+ }
+
+ } else {
+ for (k=1; k<aMidiFile.getEvent(i, j).data.getSize(); k++) {
+ out << std::dec << (int)aMidiFile.getEvent(i, j).data[k] << " ";
+ }
+ }
+ out << "\n";
+ }
+ }
+ out << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";
+ return out;
+}
+
+
+
+// md5sum: cd4fb330dd874cc263921ec55222a199 - MidiFile.cpp =css= 20030102
diff --git a/src/midiio/src/MidiFileWrite.cpp b/src/midiio/src/MidiFileWrite.cpp
new file mode 100644
index 0000000..a22e70c
--- /dev/null
+++ b/src/midiio/src/MidiFileWrite.cpp
@@ -0,0 +1,259 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Mar 15 10:55:56 GMT-0800 1998
+// Last Modified: Sun Mar 15 10:55:56 GMT-0800 1998
+// Filename: ...sig/code/control/MidiFileWrite/MidiFileWrite.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiFileWrite.cpp
+// Syntax: C++
+//
+// Description: The MidiFileWrite class will write out a Type 0 MidiFile.
+// Used for recording MIDI data streams into Standard
+// MIDI files.
+//
+
+#include "MidiFileWrite.h"
+#include "SigTimer.h"
+#include <assert.h>
+
+
+//////////////////////////////
+//
+// MidiFileWrite::MidiFileWrite
+// default value: startTime = -1
+//
+
+MidiFileWrite::MidiFileWrite(void) {
+ trackSize = 0;
+ lastPlayTime = 0;
+ midifile = NULL;
+ openQ = 0;
+}
+
+
+MidiFileWrite::MidiFileWrite(const char* aFilename, int startTime) {
+ trackSize = 0;
+ lastPlayTime = 0;
+ midifile = NULL;
+ openQ = 0;
+ setup(aFilename, startTime);
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::~MidiFileWrite
+//
+
+MidiFileWrite::~MidiFileWrite() {
+ close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::close
+//
+
+void MidiFileWrite::close(void) {
+ writeRaw(0, 0xff, 0x2f, 0); // end of track meta event
+
+ midifile->seekg(18);
+ midifile->writeBigEndian(trackSize);
+
+ midifile->close();
+
+ midifile = NULL;
+ openQ = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::setup -- writes the Midi file header and
+// prepares the midifile for writing of data
+// default value: startTime = -1
+//
+
+void MidiFileWrite::setup(const char* aFilename, int startTime) {
+ if (openQ) {
+ close();
+ }
+
+ if (midifile != NULL) delete midifile;
+ midifile = new FileIO;
+ midifile->open(aFilename, std::ios::out);
+
+ // write the header chunk
+ *midifile << "MThd"; // file identification: MIDI file
+ midifile->writeBigEndian(6L); // size of header (always 6)
+ midifile->writeBigEndian((short)0); // format: type 0;
+ midifile->writeBigEndian((short)0); // num of tracks (always 0 for type 0)
+ midifile->writeBigEndian((short)1000); // divisions per quarter note
+
+
+ // write the track header
+ *midifile << "MTrk";
+ midifile->writeBigEndian(0xffffL); // the track size which will
+ // be corrected with close()
+
+
+ // the midifile stream is now setup for writing
+ // track events
+
+ openQ = 1;
+
+ start(); // start can be called later and will behave well
+ // as long as no track events have been written
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::start
+// default value: startTime = -1;
+//
+
+void MidiFileWrite::start(int startTime) {
+ if (startTime < 0) {
+ SigTimer localTime;
+ lastPlayTime = localTime.getTime();
+ } else {
+ lastPlayTime = startTime;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeAbsolute -- considers the time data
+// to be the current time. It will generate a difference
+// time with the previously stored last playing time.
+//
+
+void MidiFileWrite::writeAbsolute(int aTime, int command, int p1, int p2) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command, (uchar)p1, (uchar)p2);
+ lastPlayTime = aTime;
+}
+
+void MidiFileWrite::writeAbsolute(int aTime, int command, int p1) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command, (uchar)p1);
+ lastPlayTime = aTime;
+}
+
+void MidiFileWrite::writeAbsolute(int aTime, int command) {
+ writeVLValue(aTime - lastPlayTime);
+ writeRaw((uchar)command);
+ lastPlayTime = aTime;
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeRaw -- write an event byte to the midifile
+//
+
+void MidiFileWrite::writeRaw(uchar aByte) {
+ assert(midifile != NULL);
+ *midifile << aByte;
+ trackSize++;
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte,
+ uchar dByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+ writeRaw(dByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar aByte, uchar bByte, uchar cByte,
+ uchar dByte, uchar eByte) {
+ writeRaw(aByte);
+ writeRaw(bByte);
+ writeRaw(cByte);
+ writeRaw(dByte);
+ writeRaw(eByte);
+}
+
+
+void MidiFileWrite::writeRaw(uchar* anArray, int arraySize) {
+ for (int i=0; i<arraySize; i++) {
+ writeRaw(anArray[i]);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeRelative -- cosiders the time data
+// to be a delta time from the last input message.
+//
+
+void MidiFileWrite::writeRelative(int aTime, int command, int p1, int p2) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command, (uchar)p1, (uchar)p2);
+ lastPlayTime += aTime;
+}
+
+void MidiFileWrite::writeRelative(int aTime, int command, int p1) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command, (uchar)p1);
+ lastPlayTime += aTime;
+}
+
+void MidiFileWrite::writeRelative(int aTime, int command) {
+ writeVLValue(aTime);
+ writeRaw((uchar)command);
+ lastPlayTime += aTime;
+}
+
+
+//////////////////////////////
+//
+// MidiFileWrite::writeVLValue -- write a number to the midifile
+// as a variable length value which segments a file into 7-bit
+// values. Maximum size of aValue is 0x7fffffff
+//
+
+void MidiFileWrite::writeVLValue(long aValue) {
+ uchar bytes[5];
+ bytes[0] = (uchar)((aValue >> 28) & 0x7f); // most significant 5 bits
+ bytes[1] = (uchar)((aValue >> 21) & 0x7f); // next largest 7 bits
+ bytes[2] = (uchar)((aValue >> 14) & 0x7f);
+ bytes[3] = (uchar)((aValue >> 7) & 0x7f);
+ bytes[4] = (uchar)((aValue) & 0x7f); // least significant 7 bits
+
+ int start = 0;
+ while (start<5 && bytes[start] == 0) start++;
+
+ for (int i=start; i<4; i++) {
+ writeRaw((uchar)(bytes[i] | 0x80));
+ }
+ writeRaw(bytes[4]);
+}
+
+// md5sum: 251468fa23862745f0cf36f359bccc17 - MidiFileWrite.cpp =css= 20030102
diff --git a/src/midiio/src/MidiIO.cpp b/src/midiio/src/MidiIO.cpp
new file mode 100644
index 0000000..26363f2
--- /dev/null
+++ b/src/midiio/src/MidiIO.cpp
@@ -0,0 +1,283 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Sun Jan 25 15:45:18 GMT-0800 1998
+// Filename: ...sig/code/control/MidiIO/MidiIO.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiIO.cpp
+// Syntax: C++
+//
+// Description: A unified class for MidiInput and MidiOutput that handles
+// MIDI input and output connections. The Synthesizer
+// and RadioBaton classes are derived from this class.
+//
+
+#include "MidiIO.h"
+
+
+//////////////////////////////
+//
+// MidiIO::MidiIO
+//
+
+MidiIO::MidiIO(void) : MidiOutput(), MidiInput() {
+ // does nothing
+}
+
+
+MidiIO::MidiIO(int outPort, int inPort) :
+ MidiOutput(outPort), MidiInput(inPort) {
+ // does nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::~MidiIO
+//
+
+MidiIO::~MidiIO() {
+ // does nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::close
+//
+
+void MidiIO::close(void) {
+ MidiInput::close();
+ MidiOutput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::closeInput
+//
+
+void MidiIO::closeInput(void) {
+ MidiInput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::closeOutput
+//
+
+void MidiIO::closeOutput(void) {
+ MidiOutput::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getChannelInOffset -- return the MIDI channel offset of
+// the MIDI input.
+//
+
+int MidiIO::getChannelInOffset(void) const {
+ return MidiInPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getChannelOutOffset -- return the MIDI channel offset of
+// the MIDI output.
+//
+
+int MidiIO::getChannelOutOffset (void) const {
+ return MidiOutPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getInputPort
+//
+
+int MidiIO::getInputPort(void) {
+ return MidiInput::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getInputTrace
+//
+
+int MidiIO::getInputTrace(void) {
+ return MidiInput::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getNumInputPorts
+//
+
+int MidiIO::getNumInputPorts(void) {
+ return MidiInput::getNumPorts();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getNumOutputPorts
+//
+
+int MidiIO::getNumOutputPorts(void) {
+ return MidiOutput::getNumPorts();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getOutputPort
+//
+
+int MidiIO::getOutputPort(void) {
+ return MidiOutput::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::getOutputTrace
+//
+
+int MidiIO::getOutputTrace(void) {
+ return MidiOutput::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::open
+//
+
+int MidiIO::open(void) {
+ if (MidiInput::open()) {
+ return MidiOutput::open();
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::openInput
+//
+
+int MidiIO::openInput(void) {
+ return MidiInput::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::openOutput
+//
+
+int MidiIO::openOutput(void) {
+ return MidiOutput::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setChannelOffset -- sets the MIDI channel offset
+//
+
+void MidiIO::setChannelOffset(int anOffset) {
+ MidiInPort::setChannelOffset(anOffset);
+ MidiOutPort::setChannelOffset(anOffset);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setInputPort
+//
+
+void MidiIO::setInputPort(int aPort) {
+ MidiInput::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setInputTrace
+//
+
+void MidiIO::setInputTrace(int aState) {
+ MidiInput::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setOutputPort
+//
+
+void MidiIO::setOutputPort(int aPort) {
+ MidiOutput::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::setOutputTrace
+//
+
+void MidiIO::setOutputTrace(int aState) {
+ MidiOutput::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiIO::toggleInputTrace
+//
+
+void MidiIO::toggleInputTrace(void) {
+ MidiInput::toggleTrace();
+}
+
+
+//////////////////////////////
+//
+// MidiIO::toggleOutputTrace
+//
+
+void MidiIO::toggleOutputTrace(void) {
+ MidiOutput::toggleTrace();
+}
+
+
+
+// md5sum: 860227c67236eb6f8897ae67f1338cb0 - MidiIO.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_alsa.cpp b/src/midiio/src/MidiInPort_alsa.cpp
new file mode 100644
index 0000000..55d22b0
--- /dev/null
+++ b/src/midiio/src/MidiInPort_alsa.cpp
@@ -0,0 +1,1038 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:03:16 PDT 2000
+// Last Modified: Sat Oct 13 16:11:10 PDT 2001 (updated for ALSA 0.9)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Last Modified: Mon Nov 19 17:52:15 PST 2001 (thread on exit improved)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "MidiInPort_alsa.h"
+#include <iostream>
+#include <stdlib.h>
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+#include <unistd.h>
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_alsa::numDevices = 0;
+int MidiInPort_alsa::objectCount = 0;
+int* MidiInPort_alsa::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_alsa::midiBuffer = NULL;
+int MidiInPort_alsa::channelOffset = 0;
+SigTimer MidiInPort_alsa::midiTimer;
+int* MidiInPort_alsa::pauseQ = NULL;
+int* MidiInPort_alsa::trace = NULL;
+std::ostream* MidiInPort_alsa::tracedisplay = &std::cout;
+Array<pthread_t> MidiInPort_alsa::midiInThread;
+int* MidiInPort_alsa::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_alsa::sysexBuffers = NULL;
+
+Array<int> MidiInPort_alsa::threadinitport;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::MidiInPort_alsa
+// default values: autoOpen = 1
+//
+
+MidiInPort_alsa::MidiInPort_alsa(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_alsa::MidiInPort_alsa(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::~MidiInPort_alsa
+//
+
+MidiInPort_alsa::~MidiInPort_alsa() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_alsa object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_alsa::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_alsa::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::close
+//
+
+void MidiInPort_alsa::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+ Sequencer_alsa::closeInput(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::closeAll --
+//
+
+void MidiInPort_alsa::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ pauseQ[i] = 1;
+ Sequencer_alsa::closeInput(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_alsa::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_alsa::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_alsa::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_alsa::getCount(void) {
+ if (getPort() == -1) return 0;
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_alsa::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_alsa::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_alsa::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_alsa::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_alsa::getPortStatus(void) {
+ return is_open_in(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_alsa::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_alsa::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_alsa::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::insert
+//
+
+void MidiInPort_alsa::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::message -- look at an incoming MIDI message
+// without extracting it from the input buffer.
+//
+
+MidiMessage& MidiInPort_alsa::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_alsa::open(void) {
+ if (getPort() == -1) return 0;
+
+ int status = Sequencer_alsa::openInput(getPort());
+ if (status) {
+ pauseQ[getPort()] = 0;
+ return 1;
+ } else {
+ pauseQ[getPort()] = 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_alsa::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_alsa::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_alsa::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setPort --
+//
+
+void MidiInPort_alsa::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+// std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+// << ", but you tried to access port: " << aPort << std::endl;
+// exit(1);
+ }
+ else {
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_alsa::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_alsa::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_alsa::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_alsa::indevcount;
+
+ if (getNumPorts() <= 0) {
+// std::cerr << "Warning: no MIDI input devices" << std::endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: memory leak on sysex buffers initialization" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ int flag;
+ midiInThread.setSize(getNumPorts());
+ threadinitport.setSize(getNumPorts());
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ threadinitport[i] = i;
+ flag = pthread_create(&midiInThread[i], NULL,
+ interpretMidiInputStreamPrivateALSA, &threadinitport[i]);
+ if (flag == -1) {
+ std::cout << "Unable to create MIDI input thread." << std::endl;
+ exit(1);
+ }
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivateALSA -- handles the MIDI input stream
+// for the various input devices from the ALSA MIDI driver.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_alsa,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_alsa::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_alsa::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_alsa::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_alsa::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivateALSA(void * arg) {
+ int portToWatch = *(int*)arg;
+ if (portToWatch < 0 || portToWatch > 1000) {
+ // the port to watch is invalid -- because the program has died
+ // before the thread function could start. Cause of invalid port
+ // data should be examined more carefully.
+ return NULL;
+ }
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[1]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_alsa::numDevices];
+ argsExpected = new int[MidiInPort_alsa::numDevices];
+ argsLeft = new int[MidiInPort_alsa::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_alsa::numDevices];
+ for (int j=0; j<MidiInPort_alsa::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = 0;
+
+ // If the all Sequencer_alsa classes have been deleted,
+ // then Sequencer_alsa::rawmidi_in will have zero size.
+ // If the size is zero, then that means the thread will be
+ // killed soon, and we do not want any processing to happen
+ // in this thread. If the port to watch is NULL, then that
+ // means that the MIDI input is not open, and we should not
+ // add any MIDI data to the input buffers. These cases are
+ // handled by the following if-else statement:
+ if (Sequencer_alsa::rawmidi_in.getSize() > 0 &&
+ Sequencer_alsa::rawmidi_in[portToWatch] != NULL) {
+ packetReadCount = snd_rawmidi_read(
+ Sequencer_alsa::rawmidi_in[portToWatch], packet, 1);
+ } else {
+ usleep(100000); // sleep for 1/10th of a second if the Input
+ // port is not open.
+ continue;
+ }
+
+
+ if (packetReadCount != 1) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+ if (Sequencer_alsa::initialized == 0) {
+ continue;
+ }
+
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = portToWatch;
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[0] == 0xfe || packet[0] == 0xf8) {
+ continue;
+ }
+
+ if (packet[0] & 0x80) { // a command byte has arrived
+ switch (packet[0] & 0xf0) {
+ case 0xf0:
+ if (packet[0] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[0] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received program change during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received aftertouch message during"
+ " sysex" << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received another message during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_alsa::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[0] != 0xf7) {
+ message[device].p0() = packet[0];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[0] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_alsa::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[0]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[0];
+ } else {
+ message[device].p2() = packet[0];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_alsa::pauseQ != NULL &&
+ MidiInPort_alsa::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_alsa
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_alsa::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_alsa::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_alsa::callbackFunction != NULL) {
+// MidiInPort_alsa::callbackFunction(device);
+// }
+ if (MidiInPort_alsa::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << ':' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_alsa::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << 'P' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ }
+ }
+ }
+
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+
+ return NULL;
+}
+
+
+
+#endif // LINUX && ALSA
+
+
+
+// md5sum: 14663a91d1f5283e05ca36399d5ab767 - MidiInPort_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_alsa05.cpp b/src/midiio/src/MidiInPort_alsa05.cpp
new file mode 100644
index 0000000..1aad849
--- /dev/null
+++ b/src/midiio/src/MidiInPort_alsa05.cpp
@@ -0,0 +1,995 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:03:16 PDT 2000
+// Last Modified: Wed Oct 3 22:28:20 PDT 2001 (frozen for ALSA 0.5)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_alsa05.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_alsa05.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux ALSA sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#if defined(LINUX) && defined(ALSA05)
+
+#include "MidiInPort_alsa05.h"
+#include <iostream.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/asoundlib.h>
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_alsa05::numDevices = 0;
+int MidiInPort_alsa05::objectCount = 0;
+int* MidiInPort_alsa05::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_alsa05::midiBuffer = NULL;
+int MidiInPort_alsa05::channelOffset = 0;
+SigTimer MidiInPort_alsa05::midiTimer;
+int* MidiInPort_alsa05::pauseQ = NULL;
+int* MidiInPort_alsa05::trace = NULL;
+ostream* MidiInPort_alsa05::tracedisplay = &cout;
+Array<pthread_t> MidiInPort_alsa05::midiInThread;
+int* MidiInPort_alsa05::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_alsa05::sysexBuffers = NULL;
+
+Array<int> MidiInPort_alsa05::threadinitport;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::MidiInPort_alsa05
+// default values: autoOpen = 1
+//
+
+MidiInPort_alsa05::MidiInPort_alsa05(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_alsa05::MidiInPort_alsa05(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::~MidiInPort_alsa05
+//
+
+MidiInPort_alsa05::~MidiInPort_alsa05() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiInPort_alsa05 object count!: "
+ << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_alsa05::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_alsa05::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::close
+//
+
+void MidiInPort_alsa05::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::closeAll --
+//
+
+void MidiInPort_alsa05::closeAll(void) {
+ Sequencer_alsa05::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_alsa05::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_alsa05::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_alsa05::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_alsa05::getCount(void) {
+ if (getPort() == -1) return 0;
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_alsa05::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_alsa05::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_alsa05::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_alsa05::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_alsa05::getPortStatus(void) {
+ return is_open_in(0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_alsa05::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_alsa05::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_alsa05::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::insert
+//
+
+void MidiInPort_alsa05::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa05::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_alsa05::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::message
+//
+
+MidiMessage& MidiInPort_alsa05::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_alsa05::open(void) {
+ if (getPort() == -1) return 0;
+
+ return Sequencer_alsa05::open();
+ pauseQ[getPort()] = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_alsa05::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_alsa05::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_alsa05::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setPort --
+//
+
+void MidiInPort_alsa05::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_alsa05::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_alsa05::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_alsa05::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa05::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_alsa05::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_alsa05::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_alsa05::indevcount;
+
+ if (getNumPorts() <= 0) {
+ cerr << "Warning: no MIDI input devices" << endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ cout << "Error: memory leak on sysex buffers initialization" << endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ int flag;
+ midiInThread.setSize(getNumPorts());
+ threadinitport.setSize(getNumPorts());
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ threadinitport[i] = i;
+ flag = pthread_create(&midiInThread[i], NULL,
+ interpretMidiInputStreamPrivateALSA05, &threadinitport[i]);
+ if (flag == -1) {
+ cout << "Unable to create MIDI input thread." << endl;
+ exit(1);
+ }
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivateALSA05 -- handles the MIDI input stream
+// for the various input devices from the ALSA MIDI driver.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_alsa05,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_alsa05::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_alsa05::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_alsa05::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the that
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_alsa05::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivateALSA05(void * arg) {
+ int portToWatch = *(int*)arg;
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[1]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_alsa05::numDevices];
+ argsExpected = new int[MidiInPort_alsa05::numDevices];
+ argsLeft = new int[MidiInPort_alsa05::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_alsa05::numDevices];
+ for (int j=0; j<MidiInPort_alsa05::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = snd_rawmidi_read(
+ Sequencer_alsa05::rawmidi_in[portToWatch], packet, 1);
+ if (packetReadCount != 1) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+ if (Sequencer_alsa05::initialized == 0) {
+ continue;
+ }
+
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = portToWatch;
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[0] == 0xfe || packet[0] == 0xf8) {
+ continue;
+ }
+
+ if (packet[0] & 0x80) { // a command byte has arrived
+ switch (packet[0] & 0xf0) {
+ case 0xf0:
+ if (packet[0] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[0] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received program change during sysex"
+ << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received aftertouch message during"
+ " sysex" << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ cout << "Error: received another message during sysex"
+ << endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_alsa05::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[0] != 0xf7) {
+ message[device].p0() = packet[0];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[0] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_alsa05::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[0]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[0];
+ } else {
+ message[device].p2() = packet[0];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_alsa05::pauseQ != NULL &&
+ MidiInPort_alsa05::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_alsa05
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_alsa05::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_alsa05::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_alsa05::callbackFunction != NULL) {
+// MidiInPort_alsa05::callbackFunction(device);
+// }
+ if (MidiInPort_alsa05::trace[device]) {
+ cout << '[' << hex << (int)message[device].p0()
+ << ':' << dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_alsa05::trace[device]) {
+ cout << '[' << hex << (int)message[device].p0()
+ << 'P' << dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << flush;
+ }
+ }
+ }
+ }
+
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+
+ return NULL;
+}
+
+
+
+#endif /* LINUX and ALSA05 */
+
+
+
+// md5sum: cc5ea6a6078cb534fc6c39543aa57a83 - MidiInPort_alsa05.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_linux.cpp b/src/midiio/src/MidiInPort_linux.cpp
new file mode 100644
index 0000000..01274e2
--- /dev/null
+++ b/src/midiio/src/MidiInPort_linux.cpp
@@ -0,0 +1,491 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 22:35:27 PDT 2000
+// Last Modified: Thu May 18 23:36:00 PDT 2000
+// Last Modified: Sat Nov 2 20:37:49 PST 2002 (added ifdef ALSA OSS)
+// Filename: ...sig/maint/code/control/MidiInPort/MidiInPort_linux.cpp
+// Web Address: http://sig.sapp.org/include/sig/MidiInPort_linux.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of an
+// operating-system specific MIDI input method.
+// Provides control of all low-level MIDI input
+// functionality such that it will work on all
+// computers in the same manner.
+//
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "MidiInPort_linux.h"
+
+
+// initialize static variables oss_input->close(); break;
+int MidiInPort_linux::objectCount = 0;
+int MidiInPort_linux::current = MIDI_IN_OSS_SELECT;
+int MidiInPort_linux::alsaQ = 0;
+int MidiInPort_linux::ossQ = 0;
+MidiInPort_oss *MidiInPort_linux::oss_input = NULL;
+MidiInPort_alsa *MidiInPort_linux::alsa_input = NULL;
+MidiInPort_unsupported *MidiInPort_linux::unknown_input = NULL;
+
+
+MidiInPort_linux::MidiInPort_linux(void) {
+ if (objectCount == 0) {
+ determineDrivers();
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiInPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+
+MidiInPort_linux::MidiInPort_linux(int aPort, int autoOpen = 1) {
+ if (objectCount == 0) {
+ determineDrivers();
+ setAndOpenPort(aPort);
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiInPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+
+MidiInPort_linux::~MidiInPort_linux() {
+ objectCount--;
+ if (objectCount == 0) {
+ if (oss_input != NULL) {
+ delete oss_input;
+ oss_input = NULL;
+ }
+ if (alsa_input != NULL) {
+ delete alsa_input;
+ alsa_input = NULL;
+ }
+ if (unknown_input != NULL) {
+ delete unknown_input;
+ unknown_input = NULL;
+ }
+ }
+
+ if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux count when destructing" << endl;
+ exit(1);
+ }
+}
+
+
+void MidiInPort_linux::clearSysex(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break;
+ default: unknown_input->clearSysex(); break;
+ }
+}
+
+
+void MidiInPort_linux::clearSysex(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->clearSysex(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->clearSysex(); break;
+ default: unknown_input->clearSysex(); break;
+ }
+}
+
+
+void MidiInPort_linux::close(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->close(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->close(); break;
+ default: unknown_input->close(); break;
+ }
+}
+
+
+void MidiInPort_linux::closeAll(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->closeAll(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->closeAll(); break;
+ default: unknown_input->closeAll(); break;
+ }
+}
+
+
+MidiMessage MidiInPort_linux::extract(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->extract(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->extract(); break;
+ default: return unknown_input->extract(); break;
+ }
+}
+
+
+int MidiInPort_linux::getBufferSize(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getBufferSize(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getBufferSize(); break;
+ default: return unknown_input->getBufferSize(); break;
+ }
+}
+
+
+int MidiInPort_linux::getChannelOffset(void) const {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getChannelOffset(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getChannelOffset(); break;
+ default: return unknown_input->getChannelOffset(); break;
+ }
+}
+
+
+int MidiInPort_linux::getCount(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getCount(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getCount(); break;
+ default: return unknown_input->getCount(); break;
+ }
+}
+
+
+const char* MidiInPort_linux::getName(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getName(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getName(); break;
+ default: return unknown_input->getName(); break;
+ }
+}
+
+
+const char* MidiInPort_linux::getName(int i) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getName(i); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getName(i); break;
+ default: return unknown_input->getName(i); break;
+ }
+}
+
+
+int MidiInPort_linux::getNumPorts(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getNumPorts(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getNumPorts(); break;
+ default: return unknown_input->getNumPorts(); break;
+ }
+}
+
+
+int MidiInPort_linux::getPort(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getPort(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getPort(); break;
+ default: return unknown_input->getPort(); break;
+ }
+}
+
+
+int MidiInPort_linux::getPortStatus(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getPortStatus(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getPortStatus(); break;
+ default: return unknown_input->getPortStatus(); break;
+ }
+}
+
+
+uchar* MidiInPort_linux::getSysex(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getSysex(buffer); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getSysex(buffer); break;
+ default: return unknown_input->getSysex(buffer); break;
+ }
+}
+
+
+int MidiInPort_linux::getSysexSize(int buffer) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getSysexSize(buffer); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getSysexSize(buffer); break;
+ default: return unknown_input->getSysexSize(buffer); break;
+ }
+}
+
+
+int MidiInPort_linux::getTrace(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->getTrace(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->getTrace(); break;
+ default: return unknown_input->getTrace(); break;
+ }
+}
+
+
+void MidiInPort_linux::insert(const MidiMessage& aMessage) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->insert(aMessage); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->insert(aMessage); break;
+ default: unknown_input->insert(aMessage); break;
+ }
+}
+
+
+int MidiInPort_linux::installSysex(uchar* anArray, int aSize) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT:
+ return oss_input->installSysex(anArray, aSize);
+ break;
+ case MIDI_IN_ALSA_SELECT:
+ return alsa_input->installSysex(anArray, aSize);
+ break;
+ default:
+ return unknown_input->installSysex(anArray, aSize);
+ break;
+ }
+}
+
+
+MidiMessage& MidiInPort_linux::message(int index) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->message(index); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break;
+ default: return unknown_input->message(index); break;
+ }
+}
+
+int MidiInPort_linux::open(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->open(); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->open(); break;
+ default: return unknown_input->open(); break;
+ }
+}
+
+
+MidiMessage& MidiInPort_linux::operator[](int index) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->message(index); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->message(index); break;
+ default: return unknown_input->message(index); break;
+ }
+}
+
+
+void MidiInPort_linux::pause(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->pause(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->pause(); break;
+ default: unknown_input->pause(); break;
+ }
+}
+
+
+void MidiInPort_linux::setBufferSize(int aSize) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setBufferSize(aSize); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setBufferSize(aSize); break;
+ default: unknown_input->setBufferSize(aSize); break;
+ }
+}
+
+
+void MidiInPort_linux::setChannelOffset(int anOffset) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setChannelOffset(anOffset); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setChannelOffset(anOffset); break;
+ default: unknown_input->setChannelOffset(anOffset); break;
+ }
+}
+
+
+void MidiInPort_linux::setAndOpenPort(int aPort) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT:
+ oss_input->setPort(aPort);
+ oss_input->open();
+ break;
+ case MIDI_IN_ALSA_SELECT:
+ alsa_input->setPort(aPort);
+ alsa_input->open();
+ break;
+ default:
+ unknown_input->setPort(aPort);
+ unknown_input->open();
+ break;
+ }
+}
+
+
+void MidiInPort_linux::setPort(int aPort) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->setPort(aPort); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->setPort(aPort); break;
+ default: unknown_input->setPort(aPort); break;
+ }
+}
+
+
+int MidiInPort_linux::setTrace(int aState) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: return oss_input->setTrace(aState); break;
+ case MIDI_IN_ALSA_SELECT: return alsa_input->setTrace(aState); break;
+ default: return unknown_input->setTrace(aState); break;
+ }
+}
+
+
+void MidiInPort_linux::toggleTrace(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->toggleTrace(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->toggleTrace(); break;
+ default: unknown_input->toggleTrace(); break;
+ }
+}
+
+
+void MidiInPort_linux::unpause(void) {
+ switch (getSelect()) {
+ case MIDI_IN_OSS_SELECT: oss_input->unpause(); break;
+ case MIDI_IN_ALSA_SELECT: alsa_input->unpause(); break;
+ default: unknown_input->unpause(); break;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::getSelect -- return the type of MIDI which
+// is being used to send MIDI output.
+//
+
+int MidiInPort_linux::getSelect(void) {
+ return current;
+}
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectOSS -- select the OSS MIDI output
+// returns 1 if OSS is available, otherwise returns 0.
+//
+
+int MidiInPort_linux::selectOSS(void) {
+ if (ossQ) {
+ current = MIDI_IN_OSS_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectALSA -- select the ALSA MIDI output
+// returns 1 if ALSA is available, otherwise returns 0.
+//
+
+int MidiInPort_linux::selectALSA(void) {
+ if (alsaQ) {
+ current = MIDI_IN_ALSA_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_linux::selectUnknown -- select the Unknown MIDI output
+// returns 1 always.
+//
+
+int MidiInPort_linux::selectUnknown(void) {
+ current = MIDI_IN_UNKNOWN_SELECT;
+ return 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+
+//////////////////////////////
+//
+// MidiInPort_linux::determineDrivers -- see if OSS/ALSA are
+// available. If /dev/sequencer is present, assume that OSS is
+// available. If /dev/snd/sdq is present, assume that ALSA is
+// available.
+//
+
+void MidiInPort_linux::determineDrivers(void) {
+ struct stat filestats;
+ int status;
+ status = stat("/dev/sequencer", &filestats);
+
+ if (status != 0) {
+ ossQ = 0;
+ } else {
+ ossQ = 1;
+ }
+
+ status = stat("/dev/snd/seq", &filestats);
+
+ if (status != 0) {
+ alsaQ = 0;
+ } else {
+ alsaQ = 1;
+ }
+
+
+ current = MIDI_IN_UNKNOWN_SELECT;
+
+ if (ossQ) {
+ current = MIDI_IN_OSS_SELECT;
+ }
+
+ if (alsaQ) {
+ current = MIDI_IN_ALSA_SELECT;
+ }
+
+ // create MIDI output types which are available:
+
+ if (oss_input != NULL) {
+ delete oss_input;
+ oss_input = NULL;
+ }
+ if (alsa_input != NULL) {
+ delete alsa_input;
+ alsa_input = NULL;
+ }
+ if (unknown_input != NULL) {
+ delete unknown_input;
+ unknown_input = NULL;
+ }
+
+ if (ossQ) {
+ oss_input = new MidiInPort_oss;
+ }
+ if (alsaQ) {
+ alsa_input = new MidiInPort_alsa;
+ }
+
+ unknown_input = new MidiInPort_unsupported;
+
+}
+
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+
+// md5sum: d634dd5c3b7e8c4d75b99d7459c3f073 - MidiInPort_linux.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_oss.cpp b/src/midiio/src/MidiInPort_oss.cpp
new file mode 100644
index 0000000..d16c865
--- /dev/null
+++ b/src/midiio/src/MidiInPort_oss.cpp
@@ -0,0 +1,1036 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Sat Jan 9 06:05:24 PST 1999
+// Last Modified: Tue Jun 29 16:18:45 PDT 1999 (added sysex capability)
+// Last Modified: Mon Dec 6 16:28:45 PST 1999
+// Last Modified: Wed Jan 12 10:59:33 PST 2000 (orphan 0xf0 behavior change)
+// Last Modified: Wed May 10 17:10:05 PDT 2000 (name change from _linux to _oss)
+// Last Modified: Fri Oct 26 14:41:36 PDT 2001 (running status for 0xa0 and 0xd0
+// fixed by Daniel Gardner)
+// Filename: ...sig/code/control/MidiInPort/linux/MidiInPort_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInPort_oss.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// linux OSS sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+//
+
+#ifdef LINUX
+
+#include "MidiInPort_oss.h"
+#include <iostream>
+#include <stdlib.h>
+#include <pthread.h>
+#include <linux/soundcard.h>
+
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+
+int MidiInPort_oss::numDevices = 0;
+int MidiInPort_oss::objectCount = 0;
+int* MidiInPort_oss::portObjectCount = NULL;
+CircularBuffer<MidiMessage>** MidiInPort_oss::midiBuffer = NULL;
+int MidiInPort_oss::channelOffset = 0;
+SigTimer MidiInPort_oss::midiTimer;
+int* MidiInPort_oss::pauseQ = NULL;
+int* MidiInPort_oss::trace = NULL;
+std::ostream* MidiInPort_oss::tracedisplay = &std::cout;
+pthread_t MidiInPort_oss::midiInThread;
+int* MidiInPort_oss::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_oss::sysexBuffers = NULL;
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::MidiInPort_oss
+// default values: autoOpen = 1
+//
+
+MidiInPort_oss::MidiInPort_oss(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_oss::MidiInPort_oss(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::~MidiInPort_oss
+//
+
+MidiInPort_oss::~MidiInPort_oss() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_oss object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_oss::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_oss::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::close
+//
+
+void MidiInPort_oss::close(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::closeAll --
+//
+
+void MidiInPort_oss::closeAll(void) {
+ Sequencer_oss::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_oss::extract(void) {
+ if (getPort() == -1) {
+ MidiMessage temp;
+ return temp;
+ }
+
+ return midiBuffer[getPort()]->extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getBufferSize -- returns the maximum possible number
+// of MIDI messages that can be stored in the buffer
+//
+
+int MidiInPort_oss::getBufferSize(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getSize();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_oss::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_oss::getCount(void) {
+ if (getPort() == -1) return 0;
+
+ return midiBuffer[getPort()]->getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until all instances
+// of MIDI classes are.
+//
+
+const char* MidiInPort_oss::getName(void) {
+ if (getPort() == -1) {
+ return "Null OSS MIDI Input";
+ }
+ return getInputName(getPort());
+}
+
+
+const char* MidiInPort_oss::getName(int i) {
+ return getInputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_oss::getNumPorts(void) {
+ return getNumInputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_oss::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_oss::getPortStatus(void) {
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_oss::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_oss::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_oss::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::insert
+//
+
+void MidiInPort_oss::insert(const MidiMessage& aMessage) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_oss::installSysex(uchar* anArray, int aSize) {
+ if (getPort() == -1) {
+ return -1;
+ } else {
+ return installSysexPrivate(getPort(), anArray, aSize);
+ }
+}
+
+//////////////////////////////
+//
+// MidiInPort_oss::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_oss::installSysexPrivate(int port, uchar* anArray, int aSize) {
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::message
+//
+
+MidiMessage& MidiInPort_oss::message(int index) {
+ if (getPort() == -1) {
+ static MidiMessage x;
+ return x;
+ }
+
+ CircularBuffer<MidiMessage>& temp = *midiBuffer[getPort()];
+ return temp[index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_oss::open(void) {
+ if (getPort() == -1) return 0;
+
+ return Sequencer_oss::open();
+ pauseQ[getPort()] = 0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keeps the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_oss::pause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_oss::setBufferSize(int aSize) {
+ if (getPort() == -1) return;
+
+ midiBuffer[getPort()]->setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setChannelOffset -- sets the MIDI chan offset,
+// either 0 or 1.
+//
+
+void MidiInPort_oss::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setPort
+//
+
+void MidiInPort_oss::setPort(int aPort) {
+// if (aPort == -1) return;
+ if (aPort < -1 || aPort >= getNumPorts()) {
+// std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+// << ", but you tried to access port: " << aPort << std::endl;
+// exit(1);
+ }
+ else {
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_oss::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_oss::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_oss::unpause(void) {
+ if (getPort() == -1) return;
+
+ pauseQ[getPort()] = 0;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_oss::deinitialize(void) {
+ closeAll();
+
+ for (int i=0; i<getNumPorts(); i++) {
+ if (sysexBuffers != NULL && sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+
+ if (sysexBuffers != NULL) {
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+
+ if (trace != NULL) {
+ delete [] trace;
+ trace = NULL;
+ }
+
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ pauseQ = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_oss::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_oss::initialize(void) {
+ // set the number of ports
+ numDevices = Sequencer_oss::indevcount;
+
+ if (getNumPorts() <= 0) {
+// std::cerr << "Warning: no MIDI input devices" << std::endl;
+ } else {
+
+ // allocate space for pauseQ, the port pause status
+ if (pauseQ != NULL) {
+ delete [] pauseQ;
+ }
+ pauseQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ }
+ portObjectCount = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (trace != NULL) {
+ delete [] trace;
+ }
+ trace = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ }
+ midiBuffer = new CircularBuffer<MidiMessage>*[numDevices];
+
+ // allocate space for Midi input sysex buffer write indices
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ }
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for Midi input sysex buffers
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: memory leak on sysex buffers initialization" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ pauseQ[i] = 0;
+ midiBuffer[i] = new CircularBuffer<MidiMessage>;
+ midiBuffer[i]->setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+ }
+
+ int flag = pthread_create(&midiInThread, NULL,
+ interpretMidiInputStreamPrivate, NULL);
+ if (flag == -1) {
+ std::cout << "Unable to create MIDI input thread." << std::endl;
+ exit(1);
+ }
+
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// friendly functions
+//
+
+
+//////////////////////////////
+//
+// interpretMidiInputStreamPrivate -- handles the MIDI input stream
+// for the various input devices.
+//
+// Note about system exclusive messages:
+// System Exclusive messages are stored in a separate buffer from
+// Other Midi messages since they can be variable in length. If
+// The Midi Input returns a message with command byte 0xf0, then
+// the p1() byte indicates the system exclusive buffer number that is
+// holding the system exclusive data for that Midi message. There
+// are 128 system exclusive buffers that are numbered between
+// 0 and 127. These buffers are filled in a cycle.
+// To extract a System exclusive message from MidiInPort_oss,
+// you first will receive a Message with a command byte of 0xf0.
+// you can then access the data for that sysex by the command:
+// MidiInPort_oss::getSysex(buffer_number), this will return
+// a pointer to the beginning of the sysex data. The first byte
+// of the sysex data should be 0xf0, and the last byte of the data
+// is 0xf7. All other bytes of data should be in the range from
+// 0 to 127. You can also get the size of the sysex buffer by the
+// following command: MidiInPort_oss::getSysexSize(buffer_number).
+// This command will tell you the number of bytes in the system
+// exclusive message including the starting 0xf0 and the ending 0xf7.
+//
+// If you want to minimize memory useage of the system exclusive
+// buffers you can run the command:
+// MidiInPort_oss::clearSysex(buffer_number); Otherwise the sysex
+// buffer will be erased automatically the next time that the that
+// buffer number is cycled through when receiving more system exclusives.
+// Allocated the allocated size of the system exclusive storage will
+// not be adjusted when the computer replaces the system exclusive
+// message unless more storage size is needed, clearSysex however,
+// will resize the sysex buffer to its default size (currently 32 bytes).
+// clearSysex() without arguments will resize all buffers so that
+// they are allocated to the default size and will erase data from
+// all buffers. You can spoof a system exclusive message coming in
+// by installing a system exclusive message and then inserting
+// the system message command into the input buffer of the MidiInPort
+// class, int sysex_buffer = MidiInPort_oss::installSysex(
+// uchar *data, int size); will put the data into a sysex buffer and
+// return the buffer number that it was placed into.
+//
+// This function assumes that System Exclusive messages cannot be sent
+// as a running status messages.
+//
+// Note about MidiMessage time stamps:
+// The MidiMessage::time field is a recording of the time that the
+// first byte of the MidiMessage arrived. If the message is from
+// running status mode, then the time that the first parameter byte
+// arrived is stored. System exclusive message arrival times are
+// recoreded at the time of the last byte (0xf7) arriving. This is
+// because other system messages can be coming in while the sysex
+// message is coming in. Anyway, sysex messages are not really to
+// be used for real time MIDI messaging, so the exact moment that the
+// first byte of the sysex came in is not important to me.
+//
+//
+
+void *interpretMidiInputStreamPrivate(void *) {
+
+ int* argsExpected = NULL; // MIDI parameter bytes expected to follow
+ int* argsLeft = NULL; // MIDI parameter bytes left to wait for
+ uchar packet[4]; // bytes for sequencer driver
+ MidiMessage* message = NULL; // holder for current MIDI message
+ int newSigTime = 0; // for millisecond timer
+ int lastSigTime = -1; // for millisecond timer
+ int zeroSigTime = -1; // for timing incoming events
+ int device = -1; // for sorting out the bytes by input device
+ Array<uchar>* sysexIn; // MIDI Input sysex temporary storage
+
+ // Note on the use of argsExpected and argsLeft for sysexs:
+ // If argsExpected is -1, then a sysex message is coming in.
+ // If argsLeft < 0, then the sysex message has not finished comming
+ // in. If argsLeft == 0 and argsExpected == -1, then the sysex
+ // has finished coming in and is to be sent to the correct
+ // location.
+
+ static int count = 0;
+ if (count != 0) {
+ std::cerr << "Cannot run this function more than once" << std::endl;
+ exit(1);
+ } else {
+ // allocate space for MIDI messages, each device has a different message
+ // holding spot in case the messages overlap in the input stream
+ message = new MidiMessage[MidiInPort_oss::numDevices];
+ argsExpected = new int[MidiInPort_oss::numDevices];
+ argsLeft = new int[MidiInPort_oss::numDevices];
+
+ sysexIn = new Array<uchar>[MidiInPort_oss::numDevices];
+ for (int j=0; j<MidiInPort_oss::numDevices; j++) {
+ sysexIn[j].allowGrowth();
+ sysexIn[j].setSize(32);
+ sysexIn[j].setSize(0);
+ sysexIn[j].setGrowth(512);
+ }
+
+ count++;
+ }
+
+ // interpret MIDI bytes as they come into the computer
+ // and repackage them as MIDI messages.
+ int packetReadCount;
+ while (1) {
+top_of_loop:
+ packetReadCount = ::read(MidiInPort_oss::sequencer_fd,
+ &packet, sizeof(packet));
+
+ if (packetReadCount != 4) {
+ // this if statement is used to prevent cases where the
+ // read function above will time out and return 0 bytes
+ // read. This if statment will also take care of -1
+ // error return values by ignoring them.
+ continue;
+ }
+
+
+/*
+ std::cout << "packet bytes "
+ << " 0x" << std::hex << (int)packet[0] // packet type
+ << " 0x" << std::hex << (int)packet[1] // possible MIDI byte
+ << " 0x" << std::hex << (int)packet[2] // device number
+ << " 0x" << std::hex << (int)packet[3] // unused for MIDI bytes
+ << std::endl;
+*/
+
+ switch (packet[0]) {
+ case SEQ_WAIT:
+ // MIDI clock ticks ... the first MIDI message deltaTime is
+ // calculated wrt the start of the MIDI clock.
+ if (zeroSigTime < 0) {
+ zeroSigTime = MidiInPort_oss::midiTimer.getTime();
+ }
+/*
+ int newTime;
+ newTime = packet[3];
+ newTime = (newTime << 8) | packet[2];
+ newTime = (newTime << 8) | packet[1];
+*/
+ break;
+
+ case SEQ_ECHO:
+ // echo events
+ break;
+
+ case SEQ_MIDIPUTC: // SEQ_MIDIPUTC = 5
+ // determination of a full MIDI message from the input MIDI
+ // stream is based here on the observation that MIDI status
+ // bytes and subsequent data bytes are NOT returned in the same
+ // read() call. Rather, they are spread out over multiple read()
+ // returns, with only a single value per return. So if we
+ // find a status byte, we then determine the number of expected
+ // operands and process that number of subsequent read()s to
+ // to determine the complete midi message.
+
+/*
+ std::cout << "MIDI byte: " << (int)packet[1] << std::endl;
+*/
+
+ // store the MIDI input device to which the incoming MIDI
+ // byte belongs.
+ device = packet[2];
+
+ // ignore the active sensing 0xfe and MIDI clock 0xf8 commands:
+ if (packet[1] == 0xfe || packet[1] == 0xf8) {
+ break;
+ }
+
+ if (packet[1] & 0x80) { // a command byte has arrived
+ switch (packet[1] & 0xf0) {
+ case 0xf0:
+ if (packet[1] == 0xf0) {
+ argsExpected[device] = -1;
+ argsLeft[device] = -1;
+ if (sysexIn[device].getSize() != 0) {
+ // ignore the command for now. It is most
+ // likely an active sensing message.
+ goto top_of_loop;
+ } else {
+ uchar datum = 0xf0;
+ sysexIn[device].append(datum);
+ }
+ } if (packet[1] == 0xf7) {
+ argsLeft[device] = 0; // indicates sysex is done
+ uchar datum = 0xf7;
+ sysexIn[device].append(datum);
+ } else if (argsExpected[device] != -1) {
+ // this is a system message that may or may
+ // not be coming while a sysex is coming in
+ argsExpected[device] = 0;
+ } else {
+ // this is a system message that is not coming
+ // while a system exclusive is coming in
+ //argsExpected[device] = 0;
+ }
+ break;
+ case 0xc0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received program change during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ case 0xd0:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received aftertouch message during"
+ " sysex" << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 1;
+ }
+ break;
+ default:
+ if (argsExpected[device] < 0) {
+ std::cout << "Error: received another message during sysex"
+ << std::endl;
+ exit(1);
+ } else {
+ argsExpected[device] = 2;
+ }
+ break;
+ }
+ if (argsExpected[device] >= 0) {
+ argsLeft[device] = argsExpected[device];
+ }
+
+ newSigTime = MidiInPort_oss::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+
+ if (packet[1] != 0xf7) {
+ message[device].p0() = packet[1];
+ }
+ message[device].p1() = 0;
+ message[device].p2() = 0;
+ message[device].p3() = 0;
+
+ if (packet[1] == 0xf7) {
+ goto sysex_done;
+ }
+ } else if (argsLeft[device]) { // not a command byte coming in
+ if (message[device].time == 0) {
+ // store the receipt time of the first message byte
+ newSigTime = MidiInPort_oss::midiTimer.getTime();
+ message[device].time = newSigTime - zeroSigTime;
+ }
+
+ if (argsExpected[device] < 0) {
+ // continue processing a sysex message
+ sysexIn[device].append(packet[1]);
+ } else {
+ // handle a message other than a sysex message
+ if (argsLeft[device] == argsExpected[device]) {
+ message[device].p1() = packet[1];
+ } else {
+ message[device].p2() = packet[1];
+ }
+ argsLeft[device]--;
+ }
+
+ // if MIDI message is complete, setup for running status, and
+ // insert note into proper buffer.
+
+ if (argsExpected[device] >= 0 && !argsLeft[device]) {
+
+ // store parameter data for running status
+ switch (message[device].p0() & 0xf0) {
+ case 0xc0: argsLeft[device] = 1; break;
+ case 0xd0: argsLeft[device] = 1; break; // fix by dan
+ default: argsLeft[device] = 2; break;
+ // 0x80 expects two arguments
+ // 0x90 expects two arguments
+ // 0xa0 expects two arguments
+ // 0xb0 expects two arguments
+ // 0xe0 expects two arguments
+ }
+
+ lastSigTime = newSigTime;
+
+ sysex_done: // come here when a sysex is completely done
+
+ // insert the MIDI message into the appropriate buffer
+ // do not insert into buffer if the MIDI input device
+ // is paused (which can mean closed). Or if the
+ // pauseQ array is pointing to NULL (which probably means that
+ // things are about to shut down).
+ if (MidiInPort_oss::pauseQ != NULL &&
+ MidiInPort_oss::pauseQ[device] == 0) {
+ if (argsExpected[device] < 0) {
+ // store the sysex in the MidiInPort_oss
+ // buffer for sysexs and return the storage
+ // location:
+ int sysexlocation =
+ MidiInPort_oss::installSysexPrivate(device,
+ sysexIn[device].getBase(),
+ sysexIn[device].getSize());
+
+ message[device].p0() = 0xf0;
+ message[device].p1() = sysexlocation;
+
+ sysexIn[device].setSize(0); // empty the sysex storage
+ argsExpected[device] = 0; // no run status for sysex
+ argsLeft[device] = 0; // turn off sysex input flag
+ }
+ MidiInPort_oss::midiBuffer[device]->insert(
+ message[device]);
+// if (MidiInPort_oss::callbackFunction != NULL) {
+// MidiInPort_oss::callbackFunction(device);
+// }
+ if (MidiInPort_oss::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << ':' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ message[device].time = 0;
+ } else {
+ if (MidiInPort_oss::trace[device]) {
+ std::cout << '[' << std::hex << (int)message[device].p0()
+ << 'P' << std::dec << (int)message[device].p1()
+ << ',' << (int)message[device].p2() << ']'
+ << std::flush;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ } // end switch
+ } // end while (1)
+
+ // This code is not yet reached, but should be made to do so eventually
+
+ if (message != NULL) {
+ delete message;
+ message = NULL;
+ }
+
+ if (argsExpected != NULL) {
+ delete argsExpected;
+ argsExpected = NULL;
+ }
+
+ if (argsLeft != NULL) {
+ delete argsLeft;
+ argsLeft = NULL;
+ }
+
+ if (sysexIn != NULL) {
+ delete sysexIn;
+ sysexIn = NULL;
+ }
+
+}
+
+
+
+#endif // LINUX
+
+
+
+// md5sum: 2008f4a298bef0cd85620a5507815866 - MidiInPort_oss.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_unsupported.cpp b/src/midiio/src/MidiInPort_unsupported.cpp
new file mode 100644
index 0000000..584a468
--- /dev/null
+++ b/src/midiio/src/MidiInPort_unsupported.cpp
@@ -0,0 +1,487 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Thu Jan 22 22:53:53 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:42:59 PDT 1999 (added sysex capability)
+// Filename: ...sig/code/control/MidiInPort/unsupported/MidiInPort_unsupported.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_unsupported.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// an unknown sound driver's specific MIDI input methods.
+// This class is inherited privately by the MidiInPort class.
+// This class is used when there is no MIDI input, so
+// that MIDI programs can otherwise be compiled and run.
+// This file can also serve as a template for creating
+// an OS specific class for MIDI input.
+//
+
+#include "MidiInPort_unsupported.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+#define DEFAULT_INPUT_BUFFER_SIZE (1024)
+
+// initialized static variables
+int MidiInPort_unsupported::numDevices = 0;
+int MidiInPort_unsupported::objectCount = 0;
+int* MidiInPort_unsupported::openQ = NULL;
+int* MidiInPort_unsupported::portObjectCount = NULL;
+CircularBuffer<MidiMessage>* MidiInPort_unsupported::midiBuffer = NULL;
+int MidiInPort_unsupported::channelOffset = 0;
+int* MidiInPort_unsupported::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_unsupported::sysexBuffers = NULL;
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::MidiInPort_unsupported
+// default values: autoOpen = 1
+//
+
+MidiInPort_unsupported::MidiInPort_unsupported(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_unsupported::MidiInPort_unsupported(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::~MidiInPort_unsupported
+//
+
+MidiInPort_unsupported::~MidiInPort_unsupported() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiInPort_unsupported object count!: "
+ << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::close
+//
+
+void MidiInPort_unsupported::close(void) {
+ if (getPortStatus() == 1) {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::closeAll
+//
+
+void MidiInPort_unsupported::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1) {
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_unsupported::extract(void) {
+ return midiBuffer[getPort()].extract();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_unsupported::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_unsupported::getCount(void) {
+ return midiBuffer[getPort()].getCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiInPort_unsupported::getName(void) {
+ return "none";
+}
+
+const char* MidiInPort_unsupported::getName(int i) {
+ return "none";
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_unsupported::getNumPorts(void) {
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_unsupported::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiInPort_unsupported::getPortStatus(void) {
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_unsupported::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::insert
+//
+
+void MidiInPort_unsupported::insert(const MidiMessage& aMessage) {
+ midiBuffer[getPort()].insert(aMessage);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::message
+//
+
+MidiMessage& MidiInPort_unsupported::message(int index) {
+ return midiBuffer[getPort()][index];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_unsupported::open(void) {
+ if (getPortStatus() == 0) {
+ openQ[getPort()] = 1;
+ }
+ return openQ[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keep the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_unsupported::pause(void) {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_unsupported::setBufferSize(int aSize) {
+ midiBuffer[getPort()].setSize(aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiInPort_unsupported::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setPort
+//
+
+void MidiInPort_unsupported::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_unsupported::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_unsupported::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_unsupported::unpause(void) {
+ // nothing
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_unsupported::deinitialize(void) {
+ int deviceCount = numDevices;
+ closeAll();
+
+ if (sysexBuffers != NULL) {
+ for (int i=0; i<deviceCount; i++) {
+ if (sysexBuffers[i] != NULL) {
+ delete [] sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ sysexWriteBuffer = NULL;
+ }
+
+ if (openQ != NULL) {
+ delete [] openQ;
+ openQ = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_unsupported::initialize(void) {
+ // get the number of ports
+ numDevices = 9;
+ if (getNumPorts() <= 0) {
+ std::cerr << "Error: no MIDI input devices" << std::endl;
+ exit(1);
+ }
+
+
+ // allocate space for sysexBuffers, the port open/close status
+ if (sysexBuffers != NULL) {
+ std::cout << "Error: sysexBuffers are not empty, don't know size" << std::endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // allocate space for sysexWriteBuffer, the port open/close status
+ if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer;
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) delete [] midiBuffer;
+ midiBuffer = new CircularBuffer<MidiMessage>[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ midiBuffer[i].setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexWriteBuffer[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_unsupported::setPortStatus
+//
+
+void MidiInPort_unsupported::setPortStatus(int aStatus) {
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+// md5sum: d8b8f65af70a9b3c33e62794c2a4a91e - MidiInPort_unsupported.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInPort_visual.cpp b/src/midiio/src/MidiInPort_visual.cpp
new file mode 100644
index 0000000..b4659bf
--- /dev/null
+++ b/src/midiio/src/MidiInPort_visual.cpp
@@ -0,0 +1,1267 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed Jan 21 22:46:30 GMT-0800 1998
+// Last Modified: Wed Jun 30 11:29:51 PDT 1999 (added sysex capability)
+// Last Modified: Wed Oct 13 10:18:22 PDT 1999 (midiInUnprepareHeader change)
+// Last Modified: Tue Nov 23 15:01:17 PST 1999 (fixed sysex NULL init)
+// Filename: ...sig/code/control/MidiInPort/visual/MidiInPort_visual.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiInPort_visual.cpp
+// Syntax: C++
+//
+// Description: An interface for MIDI input capabilities of
+// Windows 95/NT/98 specific MIDI input methods.
+// as defined in winmm.lib. This class is inherited
+// privately by the MidiInPort class.
+//
+
+#ifdef VISUAL
+
+
+#include "MidiInPort_visual.h"
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include <iostream.h>
+
+
+// initialized static variables
+int MidiInPort_visual::numDevices = 0;
+int MidiInPort_visual::objectCount = 0;
+int* MidiInPort_visual::openQ = NULL;
+int* MidiInPort_visual::inrunningQ = NULL;
+int* MidiInPort_visual::portObjectCount = NULL;
+HMIDIIN* MidiInPort_visual::device = NULL;
+MIDIHDR** MidiInPort_visual::sysexDriverBuffer1 = NULL;
+MIDIHDR** MidiInPort_visual::sysexDriverBuffer2 = NULL;
+int* MidiInPort_visual::sysexDBnumber = NULL;
+HANDLE* MidiInPort_visual::hMutex = NULL;
+CircularBuffer<MidiMessage>* MidiInPort_visual::midiBuffer = NULL;
+int MidiInPort_visual::channelOffset = 0;
+int* MidiInPort_visual::sysexWriteBuffer = NULL;
+Array<uchar>** MidiInPort_visual::sysexBuffers = NULL;
+int* MidiInPort_visual::sysexStatus = NULL;
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::MidiInPort_visual
+// default values: autoOpen = 1
+//
+
+MidiInPort_visual::MidiInPort_visual(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ trace = 0;
+ port = -1;
+ setPort(0);
+}
+
+
+MidiInPort_visual::MidiInPort_visual(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ trace = 0;
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::~MidiInPort_visual
+//
+
+MidiInPort_visual::~MidiInPort_visual() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiInPort_visual object count!: "
+ << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::clearSysex -- clears the data from a sysex
+// message and sets the allocation size to the default size (of 32
+// bytes).
+//
+
+void MidiInPort_visual::clearSysex(int buffer) {
+ buffer = 0x7f | buffer; // limit buffer range from 0 to 127
+
+ if (getPort() == -1) {
+ return;
+ }
+
+ sysexBuffers[getPort()][buffer].setSize(0);
+ if (sysexBuffers[getPort()][buffer].getAllocSize() != 32) {
+ // shrink the storage buffer's size if necessary
+ sysexBuffers[getPort()][buffer].setAllocSize(32);
+ }
+}
+
+
+void MidiInPort_visual::clearSysex(void) {
+ // clear all sysex buffers
+ for (int i=0; i<128; i++) {
+ clearSysex(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::close
+//
+
+void MidiInPort_visual::close(void) {
+ if (getPort() == -1) {
+ return;
+ }
+ if (getPortStatus() == 1 && device[getPort()] != NULL) {
+ midiInReset(device[getPort()]);
+ midiInClose(device[getPort()]);
+ uninstallSysexStuff(device[getPort()], port);
+ openQ[getPort()] = 0;
+ inrunningQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::closeAll
+//
+
+void MidiInPort_visual::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1 && device[i] != NULL) {
+ midiInReset(device[i]);
+ midiInClose(device[i]);
+ if (getPort() != 1) {
+ uninstallSysexStuff(device[getPort()], port);
+ }
+ openQ[i] = 0;
+ inrunningQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::extract -- returns the next MIDI message
+// received since that last extracted message.
+//
+
+MidiMessage MidiInPort_visual::extract(void) {
+ MidiMessage output;
+
+ waitForMutex();
+ if (getPort() != -1) {
+ output = midiBuffer[getPort()].extract();
+ }
+ releaseMutex();
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getBufferSize
+//
+
+int MidiInPort_visual::getBufferSize(void) {
+ if (getPort() != -1) {
+ return midiBuffer[getPort()].getSize();
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiInPort_visual::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getCount -- returns the number of unexamined
+// MIDI messages waiting in the input buffer.
+//
+
+int MidiInPort_visual::getCount(void) {
+ int output;
+
+ waitForMutex();
+ if (getPort() != -1) {
+ output = midiBuffer[getPort()].getCount();
+ } else {
+ output = 0;
+ }
+ releaseMutex();
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiInPort_visual::getName(void) {
+ static MIDIINCAPS inputCapabilities;
+
+ if (getPort() == -1) {
+ return "Null MIDI Input";
+ }
+
+ if (openQ[getPort()]) { // port already open
+ midiInGetDevCaps(getPort(), &inputCapabilities, sizeof(MIDIINCAPS));
+ } else { // port is currently closed
+ if(open()) {;
+ midiInGetDevCaps(getPort(), &inputCapabilities, sizeof(MIDIINCAPS));
+ close();
+ } else {
+ return "";
+ }
+ }
+ return inputCapabilities.szPname;
+}
+
+
+const char* MidiInPort_visual::getName(int i) {
+ static MIDIINCAPS inputCapabilities;
+
+ if (i < 0 || i > getNumPorts()) {
+ cerr << "Error invalid index for getName: " << i << endl;
+ exit(1);
+ }
+
+ midiInGetDevCaps(i, &inputCapabilities, sizeof(MIDIINCAPS));
+
+ return inputCapabilities.szPname;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getNumPorts -- returns the number of available
+// ports for MIDI input
+//
+
+int MidiInPort_visual::getNumPorts(void) {
+ return midiInGetNumDevs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiInPort_visual::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getPortStatus -- 0 if closed, 1 if open, 2 if
+// specifically not connected to any MIDI port.
+//
+
+int MidiInPort_visual::getPortStatus(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getSysex -- returns the sysex message contents
+// of a given buffer. You should check to see that the size is
+// non-zero before looking at the data. The data pointer will
+// be NULL if there is no data in the buffer.
+//
+
+uchar* MidiInPort_visual::getSysex(int buffer) {
+ buffer &= 0x7f; // limit the buffer access to indices 0 to 127.
+
+ if (getPort() == -1) {
+ return NULL;
+ }
+
+ if (sysexBuffers[getPort()][buffer].getSize() < 2) {
+ return NULL;
+ } else {
+ return sysexBuffers[getPort()][buffer].getBase();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getSysexSize -- returns the sysex message byte
+// count of a given buffer. Buffers are in the range from
+// 0 to 127.
+//
+
+int MidiInPort_visual::getSysexSize(int buffer) {
+ if (getPort() == -1) {
+ return 0;
+ } else {
+ return sysexBuffers[getPort()][buffer & 0x7f].getSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::getTrace -- returns true if trace is on or false
+// if trace is off. if trace is on, then prints to standard
+// output the Midi message received.
+//
+
+int MidiInPort_visual::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::insert
+//
+
+void MidiInPort_visual::insert(const MidiMessage& aMessage) {
+ waitForMutex();
+ if (getPort() == -1) {
+ // do nothing
+ } else {
+ midiBuffer[getPort()].insert(aMessage);
+ }
+ releaseMutex();
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysex -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_visual::installSysex(uchar* anArray, int aSize) {
+ return installSysexPrivate(getPort(), anArray, aSize);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysexPrivate -- put a sysex message into a
+// buffer. The buffer number that it is put into is returned.
+//
+
+int MidiInPort_visual::installSysexPrivate(int port, uchar* anArray, int aSize){
+ if (port == -1) {
+ return -1;
+ }
+
+ // choose a buffer to install sysex data into:
+ int bufferNumber = sysexWriteBuffer[port];
+ sysexWriteBuffer[port]++;
+ if (sysexWriteBuffer[port] >= 128) {
+ sysexWriteBuffer[port] = 0;
+ }
+
+ // copy contents of sysex message into the chosen buffer
+ sysexBuffers[port][bufferNumber].setSize(aSize);
+ uchar* dataptr = sysexBuffers[port][bufferNumber].getBase();
+ uchar* indataptr = anArray;
+ for (int i=0; i<aSize; i++) {
+ *dataptr = *indataptr;
+ dataptr++;
+ indataptr++;
+ }
+
+ // return the buffer number that was used
+ return bufferNumber;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::message
+//
+
+MidiMessage& MidiInPort_visual::message(int index) {
+ if (getPort() != -1) {
+ return midiBuffer[getPort()][index];
+ } else {
+ static MidiMessage nullmessage;
+ return nullmessage;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::open -- returns true if MIDI input port was
+// opened.
+//
+
+int MidiInPort_visual::open(void) {
+ if (getPort() == -1) {
+ return 1;
+ }
+
+ if (getPortStatus() == 0) {
+ int flag;
+ flag = midiInOpen(&device[getPort()], getPort(),
+ (DWORD)&midiInputCallback, (DWORD)this, CALLBACK_FUNCTION);
+ if (flag == MMSYSERR_NOERROR) {
+ openQ[getPort()] = 1;
+ installSysexStuff(device[getPort()], port);
+ unpause();
+ return 1;
+ } else { // failed to open
+ openQ[getPort()] = 0;
+ device[getPort()] = NULL;
+ return 0;
+ }
+ } else { // already open
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::pause -- stop the Midi input port from
+// inserting MIDI messages into the buffer, but keep the
+// port open. Use unpause() to reverse the effect of pause().
+//
+
+void MidiInPort_visual::pause(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (openQ[getPort()]) {
+ if (inrunningQ[getPort()] == 1) {
+ midiInStop(device[getPort()]);
+ inrunningQ[getPort()] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setBufferSize -- sets the allocation
+// size of the MIDI input buffer.
+//
+
+void MidiInPort_visual::setBufferSize(int aSize) {
+ if (getPort() != -1) {
+ midiBuffer[getPort()].setSize(aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiInPort_visual::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setPort --
+//
+
+void MidiInPort_visual::setPort(int aPort) {
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setTrace -- if false, then don't print MIDI messages
+// to the screen.
+//
+
+int MidiInPort_visual::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::toggleTrace -- switches the state of trace
+// Returns the previous value of the trace variable.
+//
+
+void MidiInPort_visual::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::unpause -- enables the Midi input port
+// to inserting MIDI messages into the buffer after the
+// port is already open.
+//
+
+void MidiInPort_visual::unpause(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (openQ[getPort()]) {
+ if (inrunningQ[getPort()] == 0) {
+ midiInStart(device[getPort()]);
+ inrunningQ[getPort()] = 1;
+ }
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_visual::deinitialize(void) {
+ int num = numDevices;
+
+ closeAll();
+
+ if (sysexBuffers != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexBuffers[i] != NULL) {
+ delete sysexBuffers[i];
+ sysexBuffers[i] = NULL;
+ }
+ }
+ delete [] sysexBuffers;
+ sysexBuffers = NULL;
+ }
+
+
+ if (sysexDriverBuffer1 != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexDriverBuffer1[i] != NULL) {
+ delete sysexDriverBuffer1[i];
+ sysexDriverBuffer1[i] = NULL;
+ }
+ }
+ delete [] sysexDriverBuffer1;
+ sysexDriverBuffer1 = NULL;
+ }
+
+ if (sysexDriverBuffer2 != NULL) {
+ for (int i=0; i<numDevices; i++) {
+ if (sysexDriverBuffer2[i] != NULL) {
+ delete sysexDriverBuffer2[i];
+ sysexDriverBuffer2[i] = NULL;
+ }
+ }
+ delete [] sysexDriverBuffer2;
+ sysexDriverBuffer2 = NULL;
+ }
+
+ if (sysexDBnumber != NULL) {
+ delete [] sysexDBnumber;
+ sysexDBnumber = NULL;
+ }
+
+
+ if (sysexWriteBuffer != NULL) {
+ delete [] sysexWriteBuffer;
+ sysexWriteBuffer = NULL;
+ }
+
+ if (sysexStatus != NULL) {
+ delete [] sysexStatus;
+ sysexStatus = NULL;
+ }
+
+ if (device != NULL) {
+ delete [] device;
+ device = NULL;
+ }
+
+ if (openQ != NULL) {
+ delete [] openQ;
+ openQ = NULL;
+ }
+
+ if (inrunningQ != NULL) {
+ delete [] inrunningQ;
+ inrunningQ = NULL;
+ }
+
+ if (hMutex != NULL) {
+ delete [] hMutex;
+ hMutex = NULL;
+ }
+
+ if (midiBuffer != NULL) {
+ delete [] midiBuffer;
+ midiBuffer = NULL;
+ }
+
+ if (portObjectCount != NULL) {
+ delete [] portObjectCount;
+ portObjectCount = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiInPort_visual::initialize(void) {
+ int i;
+
+ // get the number of ports
+ numDevices = midiInGetNumDevs();
+ if (getNumPorts() <= 0) {
+ cerr << "Error: no MIDI input devices" << endl;
+ exit(1);
+ }
+
+ // allocate space for Windoze MIDI input structures
+ if (device != NULL) {
+ cerr << "Error: device array should be NULL when calling "
+ << "initialize() in MidiInPort_visual." << endl;
+ exit(1);
+ }
+ device = new HMIDIIN[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space to keep track of an active/inactive input port
+ if (inrunningQ != NULL) delete [] inrunningQ;
+ inrunningQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for mutual exclusive
+ if (hMutex != NULL) delete [] hMutex;
+ hMutex = new HANDLE[numDevices];
+
+ // allocate space for the Midi input buffers
+ if (midiBuffer != NULL) delete [] midiBuffer;
+ midiBuffer = new CircularBuffer<MidiMessage>[numDevices];
+
+ // allocate space for the MIDI sysex buffer indices
+ if (sysexWriteBuffer != NULL) delete [] sysexWriteBuffer;
+ sysexWriteBuffer = new int[numDevices];
+
+ // allocate space for the sysex MIM_LONGDATA message tracking
+ if (sysexStatus != NULL) delete [] sysexStatus;
+ sysexStatus = new int[numDevices];
+
+ // allocate space for sysex buffers
+ if (sysexBuffers != NULL) {
+ cout << "Error: memory leak on sysex buffers initialization" << endl;
+ exit(1);
+ }
+ sysexBuffers = new Array<uchar>*[numDevices];
+
+ // allocate system exclusive buffers for MIDI driver
+ if (sysexDriverBuffer1 != NULL) {
+ cout << "Error: memory leak on sysex buffer for drivers creation" << endl;
+ exit(1);
+ }
+ sysexDriverBuffer1 = new MIDIHDR*[numDevices];
+ for (i=0; i<numDevices; i++) {
+ sysexDriverBuffer1[i] = NULL;
+ }
+
+ // allocate system exclusive buffers for MIDI driver
+ if (sysexDriverBuffer2 != NULL) {
+ cout << "Error: memory leak on sysex buffer for drivers creation" << endl;
+ exit(1);
+ }
+ sysexDriverBuffer2 = new MIDIHDR*[numDevices];
+ for (i=0; i<numDevices; i++) {
+ sysexDriverBuffer2[i] = NULL;
+ }
+
+ // allocate space for keeping track of which buffer to look at
+ if (sysexDBnumber != NULL) delete [] sysexDBnumber;
+ sysexDBnumber = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (i=0; i<getNumPorts(); i++) {
+ device[i] = NULL;
+ openQ[i] = 0;
+ inrunningQ[i] = 0;
+ portObjectCount[i] = 0;
+ hMutex[i] = CreateMutex(NULL, FALSE, "M");
+ midiBuffer[i].setSize(DEFAULT_INPUT_BUFFER_SIZE);
+
+ sysexStatus[i] = -1;
+ sysexWriteBuffer[i] = 0;
+ sysexDBnumber[i] = 0;
+ sysexBuffers[i] = new Array<uchar>[128];
+ for (int n=0; n<128; n++) {
+ sysexBuffers[i][n].allowGrowth(0); // shouldn't need to grow
+ sysexBuffers[i][n].setAllocSize(32);
+ sysexBuffers[i][n].setSize(0);
+ sysexBuffers[i][n].setGrowth(32); // in case it will ever grow
+ }
+
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::installSysexStuff -- install all the mess that
+// a MIDIIN structure needs in order to receive system exclusives.
+//
+
+void MidiInPort_visual::installSysexStuff(HMIDIIN dev, int port) {
+ if (sysexDriverBuffer1 != NULL) {
+ if (sysexDriverBuffer1[port] != NULL) {
+ // some memory leaks here
+ delete sysexDriverBuffer1[port];
+ sysexDriverBuffer1[port] = NULL;
+ }
+ }
+ if (sysexDriverBuffer2 != NULL) {
+ if (sysexDriverBuffer2[port] != NULL) {
+ // some memory leaks here
+ delete sysexDriverBuffer2[port];
+ sysexDriverBuffer2[port] = NULL;
+ }
+ }
+
+ // allocate space for Drivers sysex byte buffer
+ sysexDriverBuffer1[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE |
+ GMEM_SHARE, sizeof(MIDIHDR)));
+ sysexDriverBuffer2[port] = (LPMIDIHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE |
+ GMEM_SHARE, sizeof(MIDIHDR)));
+
+ if (sysexDriverBuffer1[port] == NULL) {
+ cout << "Error: could not allocate sysex driver's buffer" << endl;
+ exit(1);
+ }
+
+ if (sysexDriverBuffer2[port] == NULL) {
+ cout << "Error: could not allocate sysex driver's buffer" << endl;
+ exit(1);
+ }
+
+ // allocate buffer inside of sysexDriverBuffer
+ sysexDriverBuffer1[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc(
+ GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024));
+ sysexDriverBuffer2[port]->lpData = (LPSTR)GlobalLock(GlobalAlloc(
+ GMEM_MOVEABLE | GMEM_SHARE, (DWORD)1024));
+
+ if (sysexDriverBuffer1[port]->lpData == NULL) {
+ cout << "Error: there was not enought space to allocate sysex buffer"
+ << endl;
+ // leaking memory here
+ exit(1);
+ }
+
+ if (sysexDriverBuffer2[port]->lpData == NULL) {
+ cout << "Error: there was not enought space to allocate sysex buffer"
+ << endl;
+ // leaking memory here
+ exit(1);
+ }
+
+
+ // setup other sysexDriverBuffer data fields
+ sysexDriverBuffer1[port]->dwBufferLength = 1024; // total size of buffer
+ sysexDriverBuffer1[port]->dwBytesRecorded = 0L; // number of byte in buffer
+ sysexDriverBuffer1[port]->dwFlags = 0L; // initialize flags
+ sysexDriverBuffer1[port]->dwUser = 0L; // userdata: used for sysex time
+
+ // setup other sysexDriverBuffer data fields
+ sysexDriverBuffer2[port]->dwBufferLength = 1024; // total size of buffer
+ sysexDriverBuffer2[port]->dwBytesRecorded = 0L; // number of byte in buffer
+ sysexDriverBuffer2[port]->dwFlags = 0L; // initialize flags
+ sysexDriverBuffer2[port]->dwUser = 0L; // userdata: used for sysex time
+
+ // prepare the header
+ int status = midiInPrepareHeader(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error preparing sysex buffer number: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ // prepare the header
+ status = midiInPrepareHeader(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error preparing sysex buffer number: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ // add the sysex buffer to the driver
+ status = midiInAddBuffer(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error adding sysex buffer to driver: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+ status = midiInAddBuffer(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ if (status != 0) {
+ cout << "Error adding sysex buffer to driver: " << port << endl;
+ // leaking some memory here?
+ exit(1);
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::uninstallSysexStuff -- uninstalls all the mess that
+// a MIDIIN structure needs in order to receive system exclusives.
+//
+
+void MidiInPort_visual::uninstallSysexStuff(HMIDIIN dev, int port) {
+ if (port == -1) {
+ return;
+ }
+ // unprepare the headers
+ midiInUnprepareHeader(device[port], sysexDriverBuffer1[port],
+ sizeof(MIDIHDR));
+ midiInUnprepareHeader(device[port], sysexDriverBuffer2[port],
+ sizeof(MIDIHDR));
+
+ // deallocate buffer inside of sysexDriverBuffer
+ /* Following code caused problems: perhaps lpData was deleted by driver
+ delete [] sysexDriverBuffer1[port]->lpData;
+ sysexDriverBuffer1[port]->lpData = NULL;
+ delete [] sysexDriverBuffer2[port]->lpData;
+ sysexDriverBuffer2[port]->lpData = NULL;
+ */
+
+ // deallocate space for Drivers sysex byte buffer
+ delete sysexDriverBuffer1[port];
+ delete sysexDriverBuffer2[port];
+ sysexDriverBuffer1[port] = NULL;
+ sysexDriverBuffer2[port] = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::releaseMutex
+//
+
+void MidiInPort_visual::releaseMutex(void) {
+/* int flag = */ ReleaseMutex(hMutex[getPort()]);
+/*
+ if (flag != 0) {
+ cerr << "Error relasing mutex in MIDI input; flag was: " << flag << endl;
+ }
+*/
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::setPortStatus
+//
+
+void MidiInPort_visual::setPortStatus(int aStatus) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInPort_visual::waitForMutex
+//
+
+void MidiInPort_visual::waitForMutex(void) {
+/*
+ DWORD mutexResult = WaitForSingleObject(hMutex[getPort()], 5000L);
+ if (mutexResult != WAIT_OBJECT_0) {
+ cerr << "Error waiting for mutex in MIDI input" << endl;
+ }
+*/
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////
+//
+// midiInputCallback -- the function the MIDI input driver calls when
+// it has a message from the Midi in cable ready
+//
+
+void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT inputStatus,
+ DWORD instancePtr, DWORD midiMessage, DWORD timestamp) {
+ static MidiMessage newMessage;
+
+ switch (inputStatus) {
+ case MIM_MOREDATA:
+ // There is more data waiting at the device.
+ // If this case is exists, then that means that the MIDI
+ // device is too slow and some data was lost.
+ // Windows sends a MIM_MOREDATA event only if you specify
+ // the MIDI_IO_STATUS flag to midiInOpen().
+
+ // no break;
+ case MIM_DATA:
+
+ // One regular (non sysex) message has been completely
+ // received.
+
+ // ignore the Yamaha Active Sensing command and MIDI time clock
+ // at least for now.
+ if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
+ break;
+ }
+
+ newMessage.time = timestamp;
+ newMessage.data = midiMessage;
+ ((MidiInPort_visual*)instancePtr)->insert(newMessage);
+ if (((MidiInPort_visual*)instancePtr)->getTrace()) {
+ cout << "[" << hex << (int)newMessage.command() << dec
+ << ":" << (int)newMessage.p1() << ","
+ << (int)newMessage.p2() << "]";
+ cout.flush();
+ }
+ break;
+
+ case MIM_LONGDATA:
+ {
+ // A sysex or part of a sysex message is coming in.
+ // The timestamp variable contains a pointer to a
+ // MIDIHDR pointer
+
+ MIDIHDR* midiheader = (MIDIHDR*)midiMessage;
+ int dataCount = midiheader->dwBytesRecorded;
+ char* data = midiheader->lpData;
+ int port = ((MidiInPort_visual*)instancePtr)->getPort();
+ if (port == -1) {
+ break;
+ }
+ int* sysexStatus = ((MidiInPort_visual*)instancePtr)->sysexStatus;
+// MIDIHDR** sysexDriverBuffer = ((MidiInPort_visual*)instancePtr)->
+// sysexDriverBuffer;
+ HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port];
+
+ if (dataCount == 0) {
+ // can't handle a zero-length sysex
+ break;
+ }
+
+ // step 1: determine if this is the first part of the sysex
+ // message or a continuation
+ int continuation = 0;
+ if (data[0] == (char)0xf0) {
+ continuation = 0;
+ if (sysexStatus[port] != -1) {
+ cout << "Error: there is another sysex command being "
+ "received on port " << port << endl;
+ exit(1);
+ }
+ } else {
+ if (sysexStatus[port] == -1) {
+ cout << "Error: no sysex command is being "
+ "received on port " << port << endl;
+ if (data[0] < 128) {
+ cout << "First byte is: " << dec << (int)data[0] << endl;
+ } else {
+ cout << "First byte is: " << hex << (int)data[0] << endl;
+ }
+ if (data[1] < 128) {
+ cout << "Second byte is: " << dec << (int)data[1] << endl;
+ } else {
+ cout << "Second byte is: " << hex << (int)data[1] << endl;
+ }
+
+ exit(1);
+ }
+ continuation = 1;
+ }
+
+ // step 2: if continuing, add the data to the preallocated
+ // sysex buffer, otherwise, get a new buffer location
+ int buffer = -1;
+ if (continuation) {
+ buffer = sysexStatus[port];
+ if (buffer < 0 || buffer > 127) {
+ cout << "Sysex buffer was out of range: " << buffer << endl;
+ }
+ for (int i=0; i<dataCount; i++) {
+ unsigned char datum = data[i];
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].append(datum);
+ if (datum == 0xf7) {
+ for (int k=i; k<dataCount; k++) {
+ data[k-i] = data[k];
+ }
+ midiheader->dwBytesRecorded = dataCount - i - 1;
+
+ goto insert_sysex_message;
+ }
+ }
+ } else { // if not a continuation of a sysex event
+ buffer = ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port];
+ ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port]++;
+ if (buffer == 127) {
+ ((MidiInPort_visual*)instancePtr)->sysexWriteBuffer[port] = 0;
+ }
+
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].setSize(0);
+ for (int j=0; j<dataCount; j++) {
+ unsigned char datum = data[j];
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].append(datum);
+ if (datum == 0xf7) {
+ for (int k=j; k<dataCount; k++) {
+ data[k-j] = data[k];
+ }
+
+ goto insert_sysex_message;
+ }
+ }
+
+ }
+
+ // recycle the MIDI input buffer for the driver
+ {
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int dstatus = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (dstatus != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+ }
+
+ break;
+
+ insert_sysex_message:
+
+ // recycle the MIDI input buffer for the driver
+ {
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int estatus = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (estatus != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+ }
+
+ // now that a sysex message is finished, send a midimessage
+ // out to the instancePtr MIDI buffer telling the user
+ // that a sysex message has come in.
+
+ // newMessage.time = timestamp; use last time stamp that came
+ // in because the timestamp variable is used for storing
+ // the pointer of the sysex data.
+
+ newMessage.time = timestamp;
+ newMessage.p0() = 0xf0;
+ newMessage.p1() = buffer;
+ newMessage.p2() = 0;
+ newMessage.p3() = 0;
+
+ ((MidiInPort_visual*)instancePtr)->insert(newMessage);
+ if (((MidiInPort_visual*)instancePtr)->getTrace()) {
+ cout << "[" << hex << (int)newMessage.command() << dec
+ << ":" << (int)newMessage.p1() << ","
+ << (int)newMessage.p2() << "]";
+ cout.flush();
+ }
+
+ } // end of local variable range
+ break;
+
+ case MIM_ERROR:
+ // An invalid regular MIDI message was received.
+
+ break;
+
+ case MIM_LONGERROR:
+ {
+ // An invalid sysex MIDI message was received.
+
+ // if a sysex message was continuing from a previous part,
+ // then kill that message.
+
+ int port = ((MidiInPort_visual*)instancePtr)->getPort();
+ if (port == -1) {
+ break;
+ }
+ int buffer = ((MidiInPort_visual*)instancePtr)->sysexStatus[port];
+ if (buffer != -1) {
+ ((MidiInPort_visual*)instancePtr)->
+ sysexBuffers[port][buffer].setSize(0);
+ ((MidiInPort_visual*)instancePtr)->sysexStatus[port] = -1;
+ }
+
+ HMIDIIN devicex = ((MidiInPort_visual*)instancePtr)->device[port];
+ MIDIHDR* midiheader = (MIDIHDR*)midiMessage;
+
+ // recycle the MIDI input buffer for the driver
+ midiInPrepareHeader(devicex, midiheader, sizeof(MIDIHDR));
+ int status = midiInAddBuffer(devicex, midiheader, sizeof(MIDIHDR));
+ if (status != MMSYSERR_NOERROR) {
+ cout << "Error when calling midiInAddBuffer" << endl;
+ exit(1);
+ }
+
+
+ break;
+ }
+ default: ;
+ // case MIM_OPEN: // MIDI device is opening
+ // case MIM_CLOSE: // MIDI device is closing
+ }
+}
+
+
+
+#endif // VISUAL
+
+
+// md5sum: db55d9f375b86f54c0c8340547c5701f - MidiInPort_visual.cpp =css= 20030102
diff --git a/src/midiio/src/MidiInput.cpp b/src/midiio/src/MidiInput.cpp
new file mode 100644
index 0000000..93fce87
--- /dev/null
+++ b/src/midiio/src/MidiInput.cpp
@@ -0,0 +1,224 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Sun Jan 25 15:31:49 GMT-0800 1998
+// Last Modified: Thu Apr 27 17:56:03 PDT 2000 (added scale function)
+// Filename: ...sig/code/control/MidiInput/MidiInput.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiInput.cpp
+// Syntax: C++
+//
+// Description: A higher-level MIDI input interface than the
+// MidiInPort class. Can be used to allow multiple
+// objects to share a single MIDI input stream, or
+// to fake a MIDI input connection.
+//
+
+#include "MidiInput.h"
+#include <stdlib.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// MidiInput::MidiInput -- opens the specified MIDI input device and
+// sets the size of the input buffer.
+//
+
+MidiInput::MidiInput(void) : MidiInPort() {
+ orphanBuffer = NULL;
+}
+
+
+MidiInput::MidiInput(int aPort, int autoOpen) : MidiInPort(aPort, autoOpen) {
+ orphanBuffer = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::~MidiInput
+//
+
+MidiInput::~MidiInput() {
+ if (orphanBuffer != NULL) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::getBufferSize
+//
+
+int MidiInput::getBufferSize(void) {
+ if (isOrphan()) {
+ return orphanBuffer->getSize();
+ } else {
+ return MidiInPort::getBufferSize();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::getCount
+//
+
+int MidiInput::getCount(void) {
+ if (isOrphan()) {
+ return orphanBuffer->getCount();
+ } else {
+ return MidiInPort::getCount();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::extract
+//
+
+MidiMessage MidiInput::extract(void) {
+ if (isOrphan()) {
+ return orphanBuffer->extract();
+ } else {
+ return MidiInPort::extract();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// fscale -- converts a value in the range from 0 to 127
+// into a number in a new range. For example the value
+// 64 scaled to the range from 0 to 2 would be 1.
+//
+
+double MidiInput::fscale(int value, double min, double max) {
+ return value >= 127 ? max : (value/127.0*(max-min)+min);
+}
+
+
+
+//////////////////////////////
+//
+// fscale14 -- converts a value in the range from 0 to 2^15-1
+// into a number in a new range.
+//
+
+double MidiInput::fscale14(int value, double min, double max) {
+ return value >= 16383 ? max : (value/16383.0*(max-min)+min);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::insert
+//
+
+void MidiInput::insert(const MidiMessage& aMessage) {
+ if (isOrphan()) {
+ orphanBuffer->insert(aMessage);
+ } else {
+ MidiInPort::insert(aMessage);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::isOrphan
+//
+
+int MidiInput::isOrphan(void) const {
+ if (orphanBuffer == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::makeOrphanBuffer
+// default value: aSize = 1024
+//
+
+void MidiInput::makeOrphanBuffer(int aSize) {
+ if (!isOrphan()) {
+ if (orphanBuffer == NULL) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+ orphanBuffer = new CircularBuffer<MidiMessage>(aSize);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::removeOrphanBuffer
+//
+
+void MidiInput::removeOrphanBuffer(void) {
+ if (isOrphan()) {
+ delete orphanBuffer;
+ orphanBuffer = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// scale -- converts a value in the range from 0 to 127
+// into a number in a new range. For example the value
+// 64 scaled to the range from 0 to 2 would be 1.
+//
+
+int MidiInput::scale(int value, int min, int max) {
+ return value >= 127 ? max : (int)(value/127.0*(max-min+1)+min);
+}
+
+
+
+//////////////////////////////
+//
+// scale14 -- converts a value in the range from 0 to 2^15-1
+// into a number in a new range.
+//
+
+int MidiInput::scale14(int value, int min, int max) {
+ return value >= 16383 ? max : (int)(value/16383.0*(max-min+1)+min);
+}
+
+
+
+//////////////////////////////
+//
+// MidiInput::setBufferSize
+//
+
+void MidiInput::setBufferSize(int aSize) {
+ if (isOrphan()) {
+ orphanBuffer->setSize(aSize);
+ } else {
+ MidiInPort::setBufferSize(aSize);
+ }
+}
+
+
+
+// md5sum: 826d403708263eaf0089b4742179c58c - MidiInput.cpp =css= 20030102
diff --git a/src/midiio/src/MidiMessage.cpp b/src/midiio/src/MidiMessage.cpp
new file mode 100644
index 0000000..5f3df19
--- /dev/null
+++ b/src/midiio/src/MidiMessage.cpp
@@ -0,0 +1,406 @@
+//
+// Copyright 1997-1998 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 19 December 1997
+// Last Modified: Fri Jan 23 00:26:12 GMT-0800 1998
+// Last Modified: Sun Sep 20 12:17:26 PDT 1998
+// Last Modified: Mon Oct 15 14:29:12 PDT 2001 (added is_note functions)
+// Filename: ...sig/src/sigControl/MidiMessage.cpp
+// Web Address: http://sig.sapp.org/src/sigControl/MidiMessage.cpp
+// Syntax: C++
+//
+// Description: A structure for handling MIDI input messages.
+// This class stores a time stamp plus up to
+// four MIDI message bytes. System Exclusive messages
+// are stored in a separate array in the MidiInPort
+// class, and their storage index is passed to the
+// user through a MIDI message for later extraction
+// of the full sysex message.
+//
+
+#include "MidiMessage.h"
+
+
+//////////////////////////////
+//
+// MidiMessage::MidiMessage
+//
+
+MidiMessage::MidiMessage(void) {
+ // no initialization. Note that the default contents are undefined.
+}
+
+
+// default value aTime = 0
+MidiMessage::MidiMessage(int aCommand, int aP1, int aP2, int aTime) {
+ time = aTime;
+ command() = (uchar)aCommand;
+ p1() = (uchar)aP1;
+ p2() = (uchar)aP2;
+}
+
+
+MidiMessage::MidiMessage(const MidiMessage& aMessage) {
+ time = aMessage.time;
+ data = aMessage.data;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::~MidiMessage -- Destructor.
+//
+
+MidiMessage::~MidiMessage() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::command -- returns the MIDI command byte
+//
+
+uchar& MidiMessage::command(void) {
+ return p0();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::operator= -- defines how objects are to be copied
+//
+
+MidiMessage& MidiMessage::operator=(const MidiMessage& aMessage) {
+ time = aMessage.time;
+ data = aMessage.data;
+ return *this;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::operator[] -- access to byte data
+// can only access index 0 to 3, other number will be
+// chopped.
+//
+
+uchar& MidiMessage::operator[](int index) {
+ return *(((uchar*)&data)+(index & 0x3));
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p0 -- returns the command byte of the
+// midi message. Same as the command() function.
+//
+
+uchar& MidiMessage::p0(void) {
+ return *(((uchar*)&data)+0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p1 -- returns the first parameter of the
+// midi message. Valid if the command requires a parameter.
+//
+
+uchar& MidiMessage::p1(void) {
+ return *(((uchar*)&data)+1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::p2 -- returns the second parameter of the
+// midi message. Valid if the command requires two parameters.
+//
+
+uchar& MidiMessage::p2(void) {
+ return *(((uchar*)&data)+2);
+}
+
+
+//////////////////////////////
+//
+// MidiMessage::p3 -- returns the third parameter of the
+// midi message. Valid if the command requires three parameters
+// (but none of the MIDI command do).
+//
+
+uchar& MidiMessage::p3(void) {
+ return *(((uchar*)&data)+3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage:getArgCount --
+//
+
+int MidiMessage::getArgCount(void) const {
+ return getParameterCount();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getParameterCount -- returns the number
+// of valid parameters for the assiciated MIDI command
+// stored in p0. Returns -1 if MIDI command is invalid,
+// or the number of valid parameters is unknown.
+//
+
+int MidiMessage::getParameterCount(void) const {
+ int output = -1;
+ switch (*(((uchar*)&data)+0) & 0xf0) {
+ case 0x80: // note-off
+ case 0x90: // note-on
+ case 0xa0: // aftertouch
+ case 0xb0: // continuous controller
+ case 0xe0: // pitch wheel
+ output = 2;
+ break;
+ case 0xc0: // patch change
+ case 0xd0: // channel pressure
+ output = 1;
+ break;
+ case 0xf0:
+ switch (*(((uchar*)&data)+0)) {
+ // System Common Messages
+ case 0xf0: return -1; // variable for sysex
+ case 0xf1: return 1; // MIDI Time Code Quarter Frame
+ case 0xf2: return 2; // Song Position Pointer
+ case 0xf3: return 1; // Song Select
+ case 0xf4: return 0; // Undefined
+ case 0xf5: return 0; // Undefined
+ case 0xf6: return 0; // Tune Request
+ case 0xf7: return 0; // End of System exclusive
+ // System Real-Time Messages
+ case 0xf8: return 0; // Timing Clock
+ case 0xf9: return 0; // Undefined
+ case 0xfa: return 0; // Start
+ case 0xfb: return 0; // Continue
+ case 0xfc: return 0; // Stop
+ case 0xfd: return 0; // Undefined
+ case 0xfe: return 0; // Active Sensing
+ case 0xff: return 0; // System Reset
+ }
+ return -1;
+ break;
+ default: // don't know or invalid command
+ output = -1;
+ break;
+ }
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getCommand -- same as command().
+//
+
+uchar MidiMessage::getCommand(void) const {
+ return getP0();
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP0 -- same as p0().
+//
+
+uchar MidiMessage::getP0(void) const {
+ return *(((uchar*)&data)+0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP1 -- same as p1().
+//
+
+uchar MidiMessage::getP1(void) const {
+ return *(((uchar*)&data)+1);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP2 -- same as p2().
+//
+
+uchar MidiMessage::getP2(void) const {
+ return *(((uchar*)&data)+2);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::getP3 -- same as p3().
+//
+
+uchar MidiMessage::getP3(void) const {
+ return *(((uchar*)&data)+3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setCommand -- same as command().
+//
+
+void MidiMessage::setCommand(uchar aCommand) {
+ command() = aCommand;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setData -- sets the message bytes
+// default values: aP1 = 0, aP2 = 0, aP3 = 0.
+//
+
+void MidiMessage::setData(uchar aCommand, uchar aP1, uchar aP2, uchar aP3) {
+ setCommand(aCommand);
+ setP1(aP1);
+ setP2(aP2);
+ setP3(aP3);
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP0 -- same as p0().
+//
+
+void MidiMessage::setP0(uchar aP0) {
+ p0() = aP0;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP1 -- same as p1().
+//
+
+void MidiMessage::setP1(uchar aP1) {
+ p1() = aP1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP2 -- same as p2().
+//
+
+void MidiMessage::setP2(uchar aP2) {
+ p2() = aP2;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::setP3 -- same as p3().
+//
+
+void MidiMessage::setP3(uchar aP3) {
+ p3() = aP3;
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note -- Returns true if the MIDI command is 0x80 or 0x90.
+//
+
+int MidiMessage::is_note(void) {
+ if ((p0() & 0xf0) == 0x90) { // note-on or note-off
+ return 1;
+ } else if ((p0() & 0xf0) == 0x80) { // note-off
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note_on -- Returns true if the MIDI command is a note
+// on message (0x90 series with p2() > 0).
+//
+
+int MidiMessage::is_note_on(void) {
+ if (((p0() & 0xf0) == 0x90) && p2() > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiMessage::is_note_off -- Returns true if the MIDI command is a note
+// off message (0x80 series or 0x90 series with p2() == 0).
+//
+
+int MidiMessage::is_note_off(void) {
+ if ((p0() & 0xf0) == 0x80) {
+ return 1;
+ } else if (((p0() & 0xf0) == 0x90) && (p2() == 0)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////
+//
+// operator<< MidiMessage
+//
+
+std::ostream& operator<<(std::ostream& out, MidiMessage& aMessage) {
+ out << "(" << aMessage.time << ") "
+ << std::hex << (int)aMessage.getP0() << ": ";
+ for (int i=1; i<=aMessage.getArgCount(); i++) {
+ out << std::dec << (int)aMessage[i] << ' ';
+ }
+
+ return out;
+}
+
+
+
+// md5sum: 487f0fddeb8db20d81f9c039e2a460c9 - MidiMessage.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_alsa.cpp b/src/midiio/src/MidiOutPort_alsa.cpp
new file mode 100644
index 0000000..07f4e5d
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_alsa.cpp
@@ -0,0 +1,469 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Wed May 10 16:16:21 PDT 2000
+// Last Modified: Sun May 14 20:44:12 PDT 2000
+// Filename: ...sig/code/control/MidiOutPort/alsa/MidiOutPort_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_alsa.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// ALSA sound drivers. Privately inherited by the
+// MidiOutPort class via the MidiOutPort_alsa class.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "MidiOutPort_alsa.h"
+#include <iostream>
+#include <stdlib.h>
+
+// initialized static variables
+int MidiOutPort_alsa::numDevices = 0;
+int MidiOutPort_alsa::objectCount = 0;
+int* MidiOutPort_alsa::portObjectCount = NULL;
+int MidiOutPort_alsa::channelOffset = 0;
+int* MidiOutPort_alsa::trace = NULL;
+std::ostream* MidiOutPort_alsa::tracedisplay = &std::cout;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::MidiOutPort_alsa
+// default values: autoOpen = 1
+//
+
+#include <unistd.h>
+
+MidiOutPort_alsa::MidiOutPort_alsa(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_alsa::MidiOutPort_alsa(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::~MidiOutPort_alsa --
+//
+
+MidiOutPort_alsa::~MidiOutPort_alsa() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cout << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::close --
+//
+
+void MidiOutPort_alsa::close(void) {
+ Sequencer_alsa::closeOutput(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::closeAll --
+//
+
+void MidiOutPort_alsa::closeAll(void) {
+ int i;
+ for (i=0; i<getNumPorts(); i++) {
+ Sequencer_alsa::closeOutput(i);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_alsa::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_alsa::getName(void) {
+ if (getPort() == -1) {
+ return "Null ALSA Midi Output";
+ }
+ return getOutputName(getPort());
+}
+
+
+const char* MidiOutPort_alsa::getName(int i) {
+ return Sequencer_alsa::getOutputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_alsa::getNumPorts(void) {
+ return Sequencer_alsa::getNumOutputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_alsa::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_alsa::getPortStatus(void) {
+ return is_open_out(getPort());
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_alsa::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_alsa::rawsend(int command, int p1, int p2) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[3] = {(uchar)command, (uchar)p1, (uchar)p2};
+ status = write(getPort(), mdata, 3);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(int command, int p1) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[2] = {(uchar)command, (uchar)p1};
+
+ status = write(getPort(), mdata, 2);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(int command) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[1] = {(uchar)command};
+
+ status = write(getPort(), mdata, 1);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_alsa::rawsend(uchar* array, int size) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ status = write(getPort(), array, size);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(array)";
+ std::cout.flush();
+ } else {
+ std::cout << "(XarrayX)";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_alsa::open(void) {
+ if (getPort() == -1) {
+ return 2;
+ } else {
+ return Sequencer_alsa::openOutput(getPort());
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_alsa::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setPort --
+//
+
+void MidiOutPort_alsa::setPort(int aPort) {
+ if (aPort == -1) return;
+
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cout << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_alsa::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::sysex -- send a system exclusive message.
+// The message must start with a 0xf0 byte and end with
+// a 0xf7 byte.
+//
+
+int MidiOutPort_alsa::sysex(uchar* array, int size) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (size == 0 || array[0] != 0xf0 || array[size-1] != 0xf7) {
+ std::cout << "Error: invalid sysex message" << std::endl;
+ exit(1);
+ }
+
+ return rawsend(array,size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::toggleTrace --
+//
+
+void MidiOutPort_alsa::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_alsa::deinitialize(void) {
+ closeAll();
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+ if (trace != NULL) delete [] trace;
+ trace = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_alsa::initialize(void) {
+ // get the number of ports
+ numDevices = getNumOutputs();
+ if (getNumPorts() <= 0) {
+ std::cout << "Warning: no MIDI output devices" << std::endl;
+ portObjectCount = NULL;
+ trace = NULL;
+ } else {
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for trace variable for each port:
+ if (trace != NULL) delete [] trace;
+ trace = new int[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_alsa::setPortStatus --
+//
+
+void MidiOutPort_alsa::setPortStatus(int aStatus) {
+ // not used in Linux implementation
+}
+
+
+#endif /* LINUX and ALSA */
+
+
+
+// md5sum: 6f5d0ce75ae6e086ad949178e7deefcb - MidiOutPort_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_linux.cpp b/src/midiio/src/MidiOutPort_linux.cpp
new file mode 100644
index 0000000..43bba90
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_linux.cpp
@@ -0,0 +1,381 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun May 14 20:58:32 PDT 2000
+// Last Modified: Thu May 18 23:37:11 PDT 2000
+// Last Modified: Sat Nov 2 20:40:01 PST 2002 (added ALSA OSS def)
+// Filename: ...sig/code/control/MidiOutPort_linux/MidiOutPort_linux.cpp
+// Web Address: http://sig.sapp.org/include/sig/MidiOutPort_linux.cpp
+// Syntax: C++
+//
+// Description: Linux MIDI output class which detects which
+// type of MIDI drivers are available: either
+// ALSA or OSS.
+//
+
+#ifdef LINUX
+#if defined(ALSA) && defined(OSS)
+
+#include "MidiOutPort_linux.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+
+// initialize static members
+int MidiOutPort_linux::objectCount = 0;
+int MidiOutPort_linux::current = UNKNOWN_MIDI_SELECT; // MIDI out selected
+int MidiOutPort_linux::alsaQ = 0; // boolean for if ALSA is present
+int MidiOutPort_linux::ossQ = 0; // boolean for if OSS is present
+
+MidiOutPort_oss *MidiOutPort_linux::oss_output = NULL;
+MidiOutPort_alsa *MidiOutPort_linux::alsa_output = NULL;
+MidiOutPort_unsupported *MidiOutPort_linux::unknown_output = NULL;
+
+
+MidiOutPort_linux::MidiOutPort_linux(void) {
+ if (objectCount == 0) {
+ determineDrivers();
+ } else if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux object count" << endl;
+ exit(1);
+ }
+
+ objectCount++;
+}
+
+MidiOutPort_linux::MidiOutPort_linux(int aPort, int autoOpen = 1) {
+ determineDrivers();
+ setAndOpenPort(aPort);
+}
+
+MidiOutPort_linux::~MidiOutPort_linux() {
+ objectCount--;
+ if (objectCount == 0) {
+ if (oss_output != NULL) {
+ delete oss_output;
+ oss_output = NULL;
+ }
+
+ if (alsa_output != NULL) {
+ delete alsa_output;
+ alsa_output = NULL;
+ }
+
+ if (unknown_output != NULL) {
+ delete unknown_output;
+ unknown_output = NULL;
+ }
+ }
+
+ if (objectCount < 0) {
+ cout << "Error: unusual MidiOutPort_linux count when destructing" << endl;
+ exit(1);
+ }
+}
+
+
+void MidiOutPort_linux::close(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->close(); break;
+ case ALSA_MIDI_SELECT: alsa_output->close(); break;
+ default: unknown_output->close(); break;
+ }
+}
+
+void MidiOutPort_linux::closeAll(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->closeAll(); break;
+ case ALSA_MIDI_SELECT: alsa_output->closeAll(); break;
+ default: unknown_output->closeAll(); break;
+ }
+}
+
+int MidiOutPort_linux::getChannelOffset(void) const {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getChannelOffset(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getChannelOffset(); break;
+ default: return unknown_output->getChannelOffset(); break;
+ }
+}
+
+const char* MidiOutPort_linux::getName(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getName(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getName(); break;
+ default: return unknown_output->getName(); break;
+ }
+}
+
+const char* MidiOutPort_linux::getName(int i) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getName(i); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getName(i); break;
+ default: return unknown_output->getName(i); break;
+ }
+}
+
+int MidiOutPort_linux::getNumPorts(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getNumPorts(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getNumPorts(); break;
+ default: return unknown_output->getNumPorts(); break;
+ }
+}
+
+int MidiOutPort_linux::getPort(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getPort(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getPort(); break;
+ default: return unknown_output->getPort(); break;
+ }
+}
+
+int MidiOutPort_linux::getPortStatus(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getPortStatus(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getPortStatus(); break;
+ default: return unknown_output->getPortStatus(); break;
+ }
+}
+
+int MidiOutPort_linux::getTrace(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->getTrace(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->getTrace(); break;
+ default: return unknown_output->getTrace(); break;
+ }
+}
+
+int MidiOutPort_linux::open(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->open(); break;
+ case ALSA_MIDI_SELECT: return alsa_output->open(); break;
+ default: return unknown_output->open(); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command, int p1, int p2) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1, p2); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1, p2); break;
+ default: return unknown_output->rawsend(command, p1, p2); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command, int p1) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command, p1); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command, p1); break;
+ default: return unknown_output->rawsend(command, p1); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(int command) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(command); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(command); break;
+ default: return unknown_output->rawsend(command); break;
+ }
+}
+
+int MidiOutPort_linux::rawsend(uchar* array, int size) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->rawsend(array, size); break;
+ case ALSA_MIDI_SELECT: return alsa_output->rawsend(array, size); break;
+ default: return unknown_output->rawsend(array, size); break;
+ }
+}
+
+void MidiOutPort_linux::setAndOpenPort(int aPort) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT:
+ oss_output->setPort(aPort);
+ oss_output->open();
+ break;
+ case ALSA_MIDI_SELECT:
+ alsa_output->setPort(aPort);
+ alsa_output->open();
+ break;
+ default:
+ unknown_output->setPort(aPort);
+ unknown_output->open();
+ break;
+ }
+}
+
+void MidiOutPort_linux::setChannelOffset(int aChannel) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->setChannelOffset(aChannel); break;
+ case ALSA_MIDI_SELECT: alsa_output->setChannelOffset(aChannel); break;
+ default: unknown_output->setChannelOffset(aChannel); break;
+ }
+}
+
+void MidiOutPort_linux::setPort(int aPort) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->setPort(aPort); break;
+ case ALSA_MIDI_SELECT:
+ alsa_output->setPort(aPort); break;
+ default: unknown_output->setPort(aPort); break;
+ }
+}
+
+int MidiOutPort_linux::setTrace(int aState) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->setTrace(aState); break;
+ case ALSA_MIDI_SELECT: return alsa_output->setTrace(aState); break;
+ default: return unknown_output->setTrace(aState); break;
+ }
+}
+
+int MidiOutPort_linux::sysex(uchar* array, int size) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: return oss_output->sysex(array, size); break;
+ case ALSA_MIDI_SELECT: return alsa_output->sysex(array, size); break;
+ default: return unknown_output->sysex(array, size); break;
+ }
+}
+
+void MidiOutPort_linux::toggleTrace(void) {
+ switch (getSelect()) {
+ case OSS_MIDI_SELECT: oss_output->toggleTrace(); break;
+ case ALSA_MIDI_SELECT: alsa_output->toggleTrace(); break;
+ default: unknown_output->toggleTrace(); break;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::getSelect -- return the type of MIDI which
+// is being used to send MIDI output.
+//
+
+int MidiOutPort_linux::getSelect(void) {
+ return current;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectOSS -- select the OSS MIDI output
+// returns 1 if OSS is available, otherwise returns 0.
+//
+
+int MidiOutPort_linux::selectOSS(void) {
+ if (ossQ) {
+ current = OSS_MIDI_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectALSA -- select the ALSA MIDI output
+// returns 1 if ALSA is available, otherwise returns 0.
+//
+
+int MidiOutPort_linux::selectALSA(void) {
+ if (alsaQ) {
+ current = ALSA_MIDI_SELECT;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_linux::selectUnknown -- select the Unknown MIDI output
+// returns 1 always.
+//
+
+int MidiOutPort_linux::selectUnknown(void) {
+ current = UNKNOWN_MIDI_SELECT;
+ return 1;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+
+#include <unistd.h>
+
+//////////////////////////////
+//
+// MidiOutPort_linux::determineDrivers -- see if OSS/ALSA are
+// available. If /dev/sequencer is present, assume that OSS is
+// available. If /dev/snd/sdq is present, assume that ALSA is
+// available.
+//
+
+void MidiOutPort_linux::determineDrivers(void) {
+ struct stat filestats;
+ int status;
+ status = stat("/dev/sequencer", &filestats);
+
+ if (status != 0) {
+ ossQ = 0;
+ } else {
+ ossQ = 1;
+ }
+
+ status = stat("/dev/snd/seq", &filestats);
+
+ if (status != 0) {
+ alsaQ = 0;
+ } else {
+ alsaQ = 1;
+ }
+
+
+ current = UNKNOWN_MIDI_SELECT;
+
+ if (ossQ) {
+ current = OSS_MIDI_SELECT;
+ }
+
+ if (alsaQ) {
+ current = ALSA_MIDI_SELECT;
+ }
+
+ // create MIDI output types which are available:
+
+ if (oss_output != NULL) {
+ delete oss_output;
+ oss_output = NULL;
+ }
+ if (alsa_output != NULL) {
+ delete alsa_output;
+ alsa_output = NULL;
+ }
+ if (unknown_output != NULL) {
+ delete unknown_output;
+ unknown_output = NULL;
+ }
+
+ if (ossQ) {
+ oss_output = new MidiOutPort_oss;
+ }
+ if (alsaQ) {
+ alsa_output = new MidiOutPort_alsa;
+ }
+ unknown_output = new MidiOutPort_unsupported;
+}
+
+
+#endif /* ALSA and OSS */
+#endif /* LINUX */
+
+// md5sum: be1ccf667122f1c9cf56a95b2ffb8e79 - MidiOutPort_linux.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_oss.cpp b/src/midiio/src/MidiOutPort_oss.cpp
new file mode 100644
index 0000000..74f17c4
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_oss.cpp
@@ -0,0 +1,462 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Fri Dec 18 19:22:20 PST 1998
+// Last Modified: Fri Jan 8 04:26:16 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/code/control/MidiOutPort/linux/MidiOutPort_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutPort_oss.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Linux using
+// OSS sound drivers. Privately inherited by the
+// MidiOutPort class.
+//
+
+#ifdef LINUX
+
+#include "MidiOutPort_oss.h"
+#include <iostream>
+#include <stdlib.h>
+
+// initialized static variables
+int MidiOutPort_oss::numDevices = 0;
+int MidiOutPort_oss::objectCount = 0;
+int* MidiOutPort_oss::portObjectCount = NULL;
+int MidiOutPort_oss::channelOffset = 0;
+int* MidiOutPort_oss::trace = NULL;
+std::ostream* MidiOutPort_oss::tracedisplay = &std::cout;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::MidiOutPort_oss
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_oss::MidiOutPort_oss(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_oss::MidiOutPort_oss(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::~MidiOutPort_oss
+//
+
+MidiOutPort_oss::~MidiOutPort_oss() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::close
+//
+
+void MidiOutPort_oss::close(void) {
+ // don't close anything, because the
+ // Linux driver keeps all of the ports open while the
+ // midi driver (/dev/sequencer) is running.
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::closeAll
+//
+
+void MidiOutPort_oss::closeAll(void) {
+ // the Linux MIDI driver will close the /dev/sequencer device
+ // which will close all MIDI output ports at the same time.
+ Sequencer_oss::close();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_oss::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_oss::getName(void) {
+ if (getPort() == -1) {
+ return "Null OSS MIDI Output";
+ }
+ return getOutputName(getPort());
+}
+
+
+const char* MidiOutPort_oss::getName(int i) {
+ return Sequencer_oss::getOutputName(i);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_oss::getNumPorts(void) {
+ return Sequencer_oss::getNumOutputs();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_oss::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_oss::getPortStatus(void) {
+ // Linux MIDI devices are all open at the same time,
+ // so if one is open, then they all are.
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_oss::getTrace(void) {
+ if (getPort() == -1) return -1;
+
+ return trace[getPort()];
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_oss::rawsend(int command, int p1, int p2) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[3] = {(uchar)command, (uchar)p1, (uchar)p2};
+ status = write(getPort(), mdata, 3);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(int command, int p1) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[2] = {(uchar)command, (uchar)p1};
+
+ status = write(getPort(), mdata, 2);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << ":"
+ << (int)mdata[1] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << std::dec << "X"
+ << (int)mdata[1] << "," << (int)mdata[2] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(int command) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ uchar mdata[1] = {(uchar)command};
+
+ status = write(getPort(), mdata, 1);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ } else {
+ std::cout << "(" << std::hex << (int)mdata[0] << ")";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+int MidiOutPort_oss::rawsend(uchar* array, int size) {
+ if (getPort() == -1) return 0;
+
+ int status;
+ status = write(getPort(), array, size);
+
+ if (getTrace()) {
+ if (status == 1) {
+ std::cout << "(array)";
+ std::cout.flush();
+ } else {
+ std::cout << "(XarrayX)";
+ std::cout.flush();
+ }
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_oss::open(void) {
+ return Sequencer_oss::open();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_oss::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setPort --
+//
+
+void MidiOutPort_oss::setPort(int aPort) {
+ if (aPort < -1 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ if (port != -1) {
+ portObjectCount[port]++;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_oss::setTrace(int aState) {
+ if (getPort() == -1) return -1;
+
+ int oldtrace = trace[getPort()];
+ if (aState == 0) {
+ trace[getPort()] = 0;
+ } else {
+ trace[getPort()] = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::sysex -- send a system exclusive message.
+// The message must start with a 0xf0 byte and end with
+// a 0xf7 byte.
+//
+
+int MidiOutPort_oss::sysex(uchar* array, int size) {
+ if (size == 0 || array[0] != 0xf0) {
+ std::cout << "Error: invalid sysex message" << std::endl;
+ exit(1);
+ }
+
+ return rawsend(array,size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::toggleTrace
+//
+
+void MidiOutPort_oss::toggleTrace(void) {
+ if (getPort() == -1) return;
+
+ trace[getPort()] = !trace[getPort()];
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_oss::deinitialize(void) {
+ closeAll();
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+ if (trace != NULL) delete [] trace;
+ trace = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_oss::initialize(void) {
+ // get the number of ports
+ numDevices = getNumOutputs();
+ if (getNumPorts() <= 0) {
+ std::cerr << "Warning: no MIDI output devices" << std::endl;
+ portObjectCount = NULL;
+ trace = NULL;
+ } else {
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+ // allocate space for trace variable for each port:
+ if (trace != NULL) delete [] trace;
+ trace = new int[numDevices];
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ portObjectCount[i] = 0;
+ trace[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_oss::setPortStatus
+//
+
+void MidiOutPort_oss::setPortStatus(int aStatus) {
+ // not used in Linux implementation
+}
+
+
+#endif // LINUX
+
+
+
+// md5sum: c09dbe18ce8a0ff6ff11030d43a98c4a - MidiOutPort_oss.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_unsupported.cpp b/src/midiio/src/MidiOutPort_unsupported.cpp
new file mode 100644
index 0000000..f4b8c28
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_unsupported.cpp
@@ -0,0 +1,402 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Mon Jan 12 21:40:35 GMT-0800 1998
+// Last Modified: Mon Jan 12 21:40:39 GMT-0800 1998
+// Filename: ...sig/code/control/MidiOutPort/unsupported/MidiOutPort_unsupported.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_unsupported.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for basic MIDI output
+// capabilities in an unknown operating system. Privately
+// inherited by the MidiOutPort class. Used for compiling
+// and running MIDI programs on a computer with no
+// MIDI output.
+//
+
+#include "MidiOutPort_unsupported.h"
+
+#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+#include <sstream>
+
+// initialized static variables
+int MidiOutPort_unsupported::numDevices = 0;
+int MidiOutPort_unsupported::objectCount = 0;
+int* MidiOutPort_unsupported::openQ = NULL;
+int* MidiOutPort_unsupported::portObjectCount = NULL;
+int MidiOutPort_unsupported::channelOffset = 0;
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::MidiOutPort_unsupported
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_unsupported::MidiOutPort_unsupported(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_unsupported::MidiOutPort_unsupported(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::~MidiOutPort_unsupported
+//
+
+MidiOutPort_unsupported::~MidiOutPort_unsupported() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ std::cerr << "Error: bad MidiOutPort object count!: " << objectCount << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::close
+//
+
+void MidiOutPort_unsupported::close(void) {
+ if (getPortStatus() == 1) {
+ setPortStatus(0);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::closeAll
+//
+
+void MidiOutPort_unsupported::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1) {
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_unsupported::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_unsupported::getName(void) const {
+ static char* name = NULL;
+ std::stringstream temp;
+ temp << "Inactive MIDI output test port #";
+ temp << getPort();
+ if (name != NULL) delete [] name;
+ name = new char[temp.str().length()+1];
+ strcpy(name, temp.str().c_str());
+ return name;
+}
+
+const char* MidiOutPort_unsupported::getName(int i) const {
+ static char* name = NULL;
+ std::stringstream temp;
+ temp << "Inactive MIDI output test port #";
+ temp << i;
+ if (name != NULL) delete [] name;
+ name = new char[temp.str().length()+1];
+ strcpy(name, temp.str().c_str());
+ return name;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_unsupported::getNumPorts(void) const {
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_unsupported::getPort(void) const {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getPortStatus -- 0 if closed, 1 if open
+//
+
+int MidiOutPort_unsupported::getPortStatus(void) const {
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_unsupported::getTrace(void) const {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_unsupported::rawsend(int command, int p1, int p2) {
+ if (getTrace()) {
+ std::cout << "{" << std::hex << command << std::dec << ":" << (p1 & 0xff)
+ << "," << (p2 & 0xff) << "}";
+ std::cout.flush();
+ }
+
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(int command, int p1) {
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(int command) {
+ return 1;
+}
+
+
+int MidiOutPort_unsupported::rawsend(uchar* array, int size) {
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_unsupported::open(void) {
+ if (getPortStatus() == 0) {
+ openQ[getPort()] = 1;
+ }
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setChannelOffset -- sets the MIDI channel offset, either 0 or 1.
+//
+
+void MidiOutPort_unsupported::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ std::cout << "Error: Channel offset can be only 0 or 1." << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setPort --
+//
+
+void MidiOutPort_unsupported::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ std::cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << std::endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_unsupported::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::sysex --
+//
+
+int MidiOutPort_unsupported::sysex(uchar* array, int size) {
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::toggleTrace --
+//
+
+void MidiOutPort_unsupported::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_unsupported::deinitialize(void) {
+ closeAll();
+ if (openQ != NULL) delete [] openQ;
+ openQ = NULL;
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_unsupported::initialize(void) {
+ // get the number of ports
+ numDevices = 16;
+ if (getNumPorts() <= 0) {
+ std::cerr << "Error: no MIDI output devices" << std::endl;
+ exit(1);
+ }
+
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_unsupported::setPortStatus(int aStatus) {
+//
+
+void MidiOutPort_unsupported::setPortStatus(int aStatus) {
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+
+
+// md5sum: eff3d6cd2cab4c2def6ca60ef0ca197f - MidiOutPort_unsupported.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutPort_visual.cpp b/src/midiio/src/MidiOutPort_visual.cpp
new file mode 100644
index 0000000..d080817
--- /dev/null
+++ b/src/midiio/src/MidiOutPort_visual.cpp
@@ -0,0 +1,532 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Dec 28 15:18:46 GMT-0800 1997
+// Last Modified: Mon Jan 12 15:42:44 GMT-0800 1998
+// Last Modified: Tue Jun 29 13:10:30 PDT 1999 (verified sysex sending)
+// Last Modified: Tue Jun 4 22:10:16 PDT 2002 (getNumPorts fix for static use)
+// Filename: ...sig/code/control/MidiOutPort/visual/MidiOutPort_visual.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiOutPort_visual.cpp
+// Syntax: C++
+//
+// Description: Operating-System specific interface for
+// basic MIDI output capabilities in Windows 95/NT/98
+// using winmm.lib. Privately inherited by the
+// MidiOutPort class.
+//
+
+
+#ifdef VISUAL
+
+#include <iostream.h>
+#include "MidiOutPort_visual.h"
+
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+
+
+// initialized static variables
+int MidiOutPort_visual::numDevices = 0;
+int MidiOutPort_visual::objectCount = 0;
+int* MidiOutPort_visual::openQ = NULL;
+int* MidiOutPort_visual::portObjectCount = NULL;
+HMIDIOUT* MidiOutPort_visual::device = NULL;
+int MidiOutPort_visual::channelOffset = 0;
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::MidiOutPort_visual
+// default values: autoOpen = 1
+//
+
+
+MidiOutPort_visual::MidiOutPort_visual(void) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(0);
+}
+
+
+MidiOutPort_visual::MidiOutPort_visual(int aPort, int autoOpen) {
+ if (objectCount == 0) {
+ initialize();
+ }
+ objectCount++;
+
+ port = -1;
+ setPort(aPort);
+ if (autoOpen) {
+ open();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::~MidiOutPort_visual
+//
+
+MidiOutPort_visual::~MidiOutPort_visual() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitialize();
+ } else if (objectCount < 0) {
+ cerr << "Error: bad MidiOutPort object count!: " << objectCount << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::close
+//
+
+void MidiOutPort_visual::close(void) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (getPortStatus() == 1 && device[getPort()] != NULL) {
+
+ // The following function, midiOutClose, is not what I like.
+ // It will send note offs to any note which it thinks is
+ // on when the port is closed. Uncomment the line if
+ // you want this feature.
+ // midiOutReset(device[getPort()]);
+
+ midiOutClose(device[getPort()]);
+ setPortStatus(0);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::closeAll
+//
+
+void MidiOutPort_visual::closeAll(void) {
+ for (int i=0; i<getNumPorts(); i++) {
+ if (openQ[i] == 1 && device[i] != NULL) {
+ midiOutReset(device[i]);
+ midiOutClose(device[i]);
+ openQ[i] = 0;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getChannelOffset -- returns zero if MIDI channel
+// offset is 0, or 1 if offset is 1.
+//
+
+int MidiOutPort_visual::getChannelOffset(void) const {
+ return channelOffset;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getName -- returns the name of the port.
+// returns "" if no name. Name is valid until getName is called again.
+//
+
+const char* MidiOutPort_visual::getName(void) {
+ static MIDIOUTCAPS outputCapabilities;
+
+ if (getPort() == -1) {
+ return "Null MIDI Output";
+ }
+
+ if (openQ[getPort()]) { // port already open
+ midiOutGetDevCaps(getPort(), &outputCapabilities, sizeof(MIDIOUTCAPS));
+ } else { // port is currently closed
+ if(open()) {;
+ midiOutGetDevCaps(getPort(), &outputCapabilities, sizeof(MIDIOUTCAPS));
+ close();
+ } else {
+ return "";
+ }
+ }
+ return outputCapabilities.szPname;
+}
+
+
+const char* MidiOutPort_visual::getName(int i) {
+ static MIDIOUTCAPS outputCapabilities;
+
+ midiOutGetDevCaps(i, &outputCapabilities, sizeof(MIDIOUTCAPS));
+
+ return outputCapabilities.szPname;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getNumPorts -- returns the number of available
+// ports for MIDI output
+//
+
+int MidiOutPort_visual::getNumPorts(void) {
+ if (numDevices <= 0) {
+ return midiOutGetNumDevs();
+ }
+ return numDevices;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getPort -- returns the port to which this
+// object belongs (as set with the setPort function).
+//
+
+int MidiOutPort_visual::getPort(void) {
+ return port;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getPortStatus -- 0 if closed, 1 if open
+// 2 if null connection
+//
+
+int MidiOutPort_visual::getPortStatus(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (openQ[getPort()] == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::getTrace -- returns true if trace is on or
+// false if off. If trace is on, then prints to standard output
+// the Midi message being sent.
+//
+
+int MidiOutPort_visual::getTrace(void) {
+ return trace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::rawsend -- send the Midi command and its parameters
+//
+
+int MidiOutPort_visual::rawsend(int command, int p1, int p2) {
+ union { ulong word; uchar data[4]; } u;
+ u.data[0] = (uchar)command;
+ u.data[1] = (uchar)(p1 & 0x7f); // parameter limited to range 0-127;
+ u.data[2] = (uchar)(p2 & 0x7f); // parameter limited to range 0-127;
+ u.data[3] = 0;
+
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ int flag = midiOutShortMsg(device[getPort()], u.word);
+
+ if (getTrace()) {
+ if (flag == MMSYSERR_NOERROR) {
+ cout << "(" << hex << (int)u.data[0] << dec << ":"
+ << (int)u.data[1] << "," << (int)u.data[2] << ")";
+ cout.flush();
+ } else {
+ cout << "(" << hex << (int)u.data[0] << dec << "X"
+ << (int)u.data[1] << "," << (int)u.data[2] << ")";
+ cout.flush();
+ }
+ }
+
+ return flag;
+}
+
+
+int MidiOutPort_visual::rawsend(int command, int p1) {
+ return rawsend(command, p1, 0);
+}
+
+
+int MidiOutPort_visual::rawsend(int command) {
+ return rawsend(command, 0, 0);
+}
+
+
+int MidiOutPort_visual::rawsend(uchar* array, int size) {
+ // Note: this function will work in Windows 95 and Windows NT.
+ // This function will not work in Windows 3.x because a
+ // different memory model is necessary.
+
+ if (size > 64000 || size < 1) {
+ cerr << "Warning: cannot write a MIDI stream larger than 64kB" << endl;
+ return 0;
+ }
+
+ MIDIHDR midiheader; // structure for sending an array of MIDI bytes
+
+ midiheader.lpData = (char *)array;
+ midiheader.dwBufferLength = size;
+ // midiheader.dwBytesRecorded = size; // example program doesn't set
+ midiheader.dwFlags = 0; // flags must be set to 0
+
+ if (getPort() == -1) {
+ return -1;
+ }
+
+ int status = midiOutPrepareHeader(device[getPort()], &midiheader,
+ sizeof(MIDIHDR));
+
+ if (status != MMSYSERR_NOERROR) {
+ return 0;
+ }
+
+ status = midiOutLongMsg(device[getPort()], &midiheader, sizeof(MIDIHDR));
+
+ if (status != MMSYSERR_NOERROR) {
+ return 0;
+ }
+
+ while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader(device[getPort()],
+ &midiheader, sizeof(MIDIHDR))) {
+ Sleep(1); // sleep for 1 millisecond
+ }
+
+ return 1;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::open -- returns true if MIDI output port was
+// opened.
+//
+
+int MidiOutPort_visual::open(void) {
+ if (getPort() == -1) {
+ return 2;
+ }
+
+ if (getPortStatus() == 0) {
+ int flag;
+ flag = midiOutOpen(&device[getPort()], getPort(), 0, 0, CALLBACK_NULL);
+ if (flag == MMSYSERR_NOERROR) {
+ openQ[getPort()] = 1;
+ return 1;
+ } else { // faied to open
+ openQ[getPort()] = 0;
+ device[getPort()] = NULL;
+ return 0;
+ }
+ } else { // already open
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setChannelOffset -- sets the MIDI channel offset,
+// either 0 or 1.
+//
+
+void MidiOutPort_visual::setChannelOffset(int anOffset) {
+ switch (anOffset) {
+ case 0: channelOffset = 0; break;
+ case 1: channelOffset = 1; break;
+ default:
+ cout << "Error: Channel offset can be only 0 or 1." << endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setPort
+//
+
+void MidiOutPort_visual::setPort(int aPort) {
+ if (aPort < 0 || aPort >= getNumPorts()) {
+ cerr << "Error: maximum port number is: " << getNumPorts()-1
+ << ", but you tried to access port: " << aPort << endl;
+ exit(1);
+ }
+
+ if (port != -1) {
+ portObjectCount[port]--;
+ }
+ port = aPort;
+ portObjectCount[port]++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setTrace -- if false, then won't print
+// Midi messages to standard output.
+//
+
+int MidiOutPort_visual::setTrace(int aState) {
+ int oldtrace = trace;
+ if (aState == 0) {
+ trace = 0;
+ } else {
+ trace = 1;
+ }
+ return oldtrace;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::sysex -- send a system exclusive message.
+// The first byte of the message must be a 0xf0 byte.
+//
+
+int MidiOutPort_visual::sysex(uchar* array, int size) {
+ if (size == 0 || array[0] != 0xf0) {
+ cout << "Error: invalid system exclusive message,"
+ " first byte must be 0xf0" << endl;
+ exit(1);
+ }
+
+ return rawsend(array, size);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::toggleTrace
+//
+
+void MidiOutPort_visual::toggleTrace(void) {
+ trace = !trace;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Private functions
+//
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::deinitialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_visual::deinitialize(void) {
+ closeAll();
+ if (device != NULL) delete [] device;
+ device = NULL;
+ if (openQ != NULL) delete [] openQ;
+ openQ = NULL;
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::initialize -- sets up storage if necessary
+// This function should be called if the current object is
+// the first object to be created.
+//
+
+void MidiOutPort_visual::initialize(void) {
+ // get the number of ports
+ numDevices = midiOutGetNumDevs();
+ if (getNumPorts() <= 0) {
+ cerr << "Error: no MIDI output devices" << endl;
+ exit(1);
+ }
+
+ // allocate space for Windoze MIDI output structures
+ if (device != NULL) {
+ cerr << "Error: device array should be NULL when calling "
+ << "initialize() in MidiOutPort." << endl;
+ exit(1);
+ }
+ device = new HMIDIOUT[numDevices];
+
+ // allocate space for openQ, the port open/close status
+ if (openQ != NULL) delete [] openQ;
+ openQ = new int[numDevices];
+
+ // allocate space for object count on each port:
+ if (portObjectCount != NULL) delete [] portObjectCount;
+ portObjectCount = new int[numDevices];
+
+
+ // initialize the static arrays
+ for (int i=0; i<getNumPorts(); i++) {
+ device[i] = NULL;
+ openQ[i] = 0;
+ portObjectCount[i] = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutPort_visual::setPortStatus
+//
+
+void MidiOutPort_visual::setPortStatus(int aStatus) {
+ if (getPort() == -1) {
+ return;
+ }
+
+ if (aStatus) {
+ openQ[getPort()] = 1;
+ } else {
+ openQ[getPort()] = 0;
+ }
+}
+
+
+#endif // VISUAL
+
+
+
+
+// md5sum: 8cb60bfb5dc9ea42808ffa4540e0fc52 - MidiOutPort_visual.cpp =css= 20030102
diff --git a/src/midiio/src/MidiOutput.cpp b/src/midiio/src/MidiOutput.cpp
new file mode 100644
index 0000000..d78460f
--- /dev/null
+++ b/src/midiio/src/MidiOutput.cpp
@@ -0,0 +1,1082 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 18 December 1997
+// Last Modified: Mon Jan 26 23:54:36 GMT-0800 1998
+// Last Modified: Tue Feb 2 08:30:28 PST 1999
+// Last Modified: Sun Jul 18 18:52:29 PDT 1999 (added RPN functions)
+// Last Modified: Sun Dec 9 15:01:33 PST 2001 (switched con/des code)
+// Filename: ...sig/code/control/MidiOutput/MidiOutput.cpp
+// Web Address: http://sig.sapp.org/src/sig/MidiOutput.cpp
+// Syntax: C++
+//
+// Description: The MIDI output interface for MIDI synthesizers/equipment
+// which has many convienience functions defined for
+// various types of MIDI output.
+//
+
+#include "MidiOutput.h"
+#include <iostream>
+#include <iomanip>
+
+#define RECORD_ASCII (0)
+#define RECORD_BINARY (1)
+#define RECORD_MIDI_FILE (2)
+
+
+// declaration of static variables
+SigTimer MidiOutput::timer;
+Array<int>* MidiOutput::rpn_lsb_status = NULL;
+Array<int>* MidiOutput::rpn_msb_status = NULL;
+int MidiOutput::objectCount = 0;
+
+
+//////////////////////////////
+//
+// MidiOutput::MidiOutput --
+//
+
+
+MidiOutput::MidiOutput(void) : MidiOutPort() {
+ outputRecordQ = 0;
+
+ if (objectCount == 0) {
+ initializeRPN();
+ }
+ objectCount++;
+}
+
+
+
+MidiOutput::MidiOutput(int aPort, int autoOpen) : MidiOutPort(aPort, autoOpen) {
+ outputRecordQ = 0;
+
+ if (objectCount == 0) {
+ initializeRPN();
+ }
+ objectCount++;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::~MidiOutput
+//
+
+MidiOutput::~MidiOutput() {
+ objectCount--;
+ if (objectCount == 0) {
+ deinitializeRPN();
+ } else if (objectCount < 0) {
+ std::cout << "Error in MidiOutput decontruction" << std::endl;
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::cont -- send a controller command MIDI message.
+//
+// channel = the Midi channel ofset from 0 [0..15]
+// controller = the continuous controller number [0..127]
+// data = the value of the specified controller [0..127]
+//
+
+int MidiOutput::cont(int channel, int controller, int data) {
+ return send(0xb0 | (channel & 0x0f), controller, data);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::off -- sends a Note Off MIDI message (0x80).
+//
+// channel = MIDI channel to send note on. range is [0..15]
+// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127]
+// velocity = release velocity of the note, 127 = quickest possible
+//
+// Note: The more common method of turning off a note is to use the
+// play() function (midi command 0x90) but send an attack velocity of 0.
+//
+
+int MidiOutput::off(int channel, int keynum, int releaseVelocity) {
+ return send(0x80 | (channel & 0x0f), keynum, releaseVelocity);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pc -- send a patch change MIDI message. changes the timbre
+// on the specified channel.
+//
+// channel = MIDI channel to which to send the patch change [0..15]
+// timbre = the voice to select on the specified channel [0..127]
+//
+
+int MidiOutput::pc(int channel, int timbre) {
+ return send(0xc0 | (channel & 0x0f), timbre);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::play -- sends a Note On/Off MIDI message.
+//
+// channel = MIDI channel to send note on. range is [0..15]
+// keynum = MIDI key number to play (middle C = 60, C# = 61, etc.) [0..127]
+// velocity = attack velocity of the note, 0 = 0ff, 127 = loudest possible
+//
+
+int MidiOutput::play(int channel, int keynum, int velocity) {
+ return send(0x90 | (channel & 0x0f), keynum, velocity);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: send a MIDI pitch bend.
+// Parameters are:
+// 1. channel -- MIDI channel offset from 0.
+// 2. mostByte -- most significant 7 bits (coarse tuning)
+// 3. leastByte -- least significant 7 bits (fine tuning)
+//
+
+int MidiOutput::pw(int channel, int mostByte, int leastByte) {
+ return send(0xe0 | (channel & 0x0f), leastByte, mostByte);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: 14 bit number given as input
+// range for 14 bit number is 0 to 16383.
+//
+
+int MidiOutput::pw(int channel, int tuningData) {
+ uchar greaterBits = (uchar)((tuningData >> 7) & 0x7f);
+ uchar lesserBits = (uchar)(tuningData & 0x7f);
+ return pw(channel, greaterBits, lesserBits);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::pw -- Pitch Wheel: range between -1 to 1 given as input.
+// Range is then converted to a 14 bit number.
+// +1 = highest value of pitch wheel
+// 0 = rest position of pitch wheel
+// -1 = lowest value of pitch wheel
+//
+
+int MidiOutput::pw(int channel, double tuningData) {
+ if (tuningData < -1.0 || tuningData > 1.0) {
+ std::cerr << "Error: pitch wheel data is out of range: " << tuningData << std::endl;
+ exit(1);
+ }
+
+ int output = (int)((tuningData+1.0)/2.0*16383 + 0.5);
+ return pw(channel, output);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::recordStart
+//
+
+void MidiOutput::recordStart(char *filename, int format) {
+ if (outputRecordQ) { // already recording, so close old file
+ recordStop();
+ }
+
+ outputRecordFile.open(filename, std::ios::out);
+ if (!outputRecordFile) { // open file failed
+ std::cerr << "Error: cannot open file " << filename << std::endl;
+ outputRecordQ = 0;
+ } else {
+ outputRecordQ = 1;
+ }
+
+ if (outputRecordQ) {
+ switch (format) {
+ case RECORD_ASCII: // ascii
+ outputRecordType = RECORD_ASCII;
+ outputRecordFile <<"; delta time/MIDI output at delta time" << std::endl;
+ break;
+ case RECORD_BINARY: // binary
+ outputRecordType = RECORD_BINARY;
+ // record the magic number for binary format
+ outputRecordFile << (uchar)0xf8 << (uchar)0xf8
+ << (uchar)0xf8 << (uchar)0xf8;
+ break;
+ case RECORD_MIDI_FILE: // standard MIDI file, type 0
+ default:
+ outputRecordType = RECORD_MIDI_FILE;
+ // header stuff to be written here
+ break;
+ }
+ }
+
+ lastFlushTime = timer.getTime();
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::recordStop
+//
+
+void MidiOutput::recordStop(void) {
+ if (outputRecordQ) {
+ outputRecordQ = 0;
+ outputRecordFile.close();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::reset -- sends the MIDI command 0xFF which
+// should force the MIDI devices on the other side of the
+// MIDI cable into their power-on reset condition, clear running
+// status, turn off any sounding notes, set Local Control on, and
+// otherwise clean up the state of things.
+//
+
+void MidiOutput::reset(void) {
+ send(0xff, 0, 0);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::send -- send a byte to the MIDI port but record it
+// first.
+//
+
+int MidiOutput::send(int command, int p1, int p2) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, p1, p2);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, p1, p2);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, p1, p2);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command, p1, p2);
+}
+
+
+int MidiOutput::send(int command, int p1) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, p1, -1);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, p1, -1);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, p1, -1);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command, p1);
+}
+
+
+int MidiOutput::send(int command) {
+ if (outputRecordQ) {
+ switch (outputRecordType) {
+ case 0: // ascii
+ writeOutputAscii(command, -1, -1);
+ break;
+ case 1: // binary
+ writeOutputBinary(command, -1, -1);
+ break;
+ case 2: // standard MIDI file type 0
+ writeOutputMidifile(command, -1, -1);
+ break;
+ }
+ lastFlushTime = timer.getTime(); // only keep track if recording
+ }
+ return rawsend(command);
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::silence -- send a note off to all notes on all channels.
+// default value: aChannel = -1
+//
+
+void MidiOutput::silence(int aChannel) {
+ int keyno;
+ if (aChannel == -1) {
+ for (int channel=0; channel<16; channel++) {
+ for (keyno=0; keyno<128; keyno++) {
+ play(channel, keyno, 0);
+ }
+ }
+ } else {
+ for (keyno=0; keyno<128; keyno++) {
+ play(aChannel, keyno, 0);
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::sustain -- set the MIDI sustain continuous controller on or off.
+// Equivalent to the command cont(channel, 0x40, status).
+//
+
+void MidiOutput::sustain(int channel, int status) {
+ if (status) { // turn on sustain
+ cont(channel, 0x40, 127);
+ } else { // turn off sustain
+ cont(channel, 0x40, 0);
+ }
+}
+
+
+
+///////////////////////////////
+//
+// MidiOutput::sysex -- sends a system exclusive MIDI message.
+// you must supply the 0xf0 at the start of the array
+// and the 0xf7 at the end of the array.
+//
+
+int MidiOutput::sysex(char* data, int length) {
+ return rawsend((uchar*)data, length);
+}
+
+
+int MidiOutput::sysex(uchar* data, int length) {
+ return rawsend(data, length);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// RPN functions
+//
+
+
+//////////////////////////////
+//
+// NRPN -- sends a Non-registered parameter number where:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN MSB data (controller #6 data)
+// [parameter #5: NRPN LSB data (controller #38 data)]
+// or:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data)
+//
+//
+// NRPN (Non-registered parameter number) -- General MIDI and
+// Extended MIDI mess. It becomes the receiving synthesizer's
+// responsibility to determine the meaning of continuous
+// controller (ccont) #6 from data sent with cconts #98,99 (for
+// NRPNS) and cconts #100,101 (for RPNS). NRPN parameters
+// are not reset when the ccont#121 is sent to reset controllers.
+//
+// NRPN's are "non-standard" meaning that any synthesizer could
+// do whatever they want with a given NRPN; However, the
+// GS and XG specifications are given in the table further below.
+//
+// The data for NRPNs are transfered to synthesizer with
+// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment
+// ccont#96 (data increment) and ccont#97 (data decrement) are in
+// relation to the RPN or NRPN in effect. Increment and Decrement
+// are not recommend to use with RPN's because of confusion in the
+// MIDI industry over which 7-bit data (#6 or #38) to increment.
+//
+// Once you have selected an NRPN on a given channel, the
+// channel will apply subsequent Data Entry to the
+// selected parameter. After making the necessary settings
+// you should set NRPN to NULL to reduce the risk of
+// operational errors. a NUL RPN will disable the previous
+// values of either RPN or NRPN data.
+//
+// The following NRPN values are supported in Yamaha's XG specification:
+// CCont #98 = LSB of NRPN parameter ID
+// CCont #99 = MSB of NRPN parameter ID
+//
+// NRPN
+// MSB LSB Data Range
+// #99 #98 Parameter (ccont#6=MSB, ccont#38=LSB)
+// === ===== ====================== ======================
+// 1 8 Vibrato Rate -64.. 0..+63 logical range or (-50..+50)
+// 0..64..127 MIDI data range ( 14..114)
+// 1 9 Vibrato Depth same ranges as above
+// 1 10 Vibrato Delay same ranges as above
+// 1 32 Filter Cutoff Freq. same ranges as above
+// 1 33 Filter Resonance same ranges as above
+// 1 99 EG Attack Time same ranges as above
+// 1 100 EG Decay Time same ranges as above
+// 1 102 EG Release Time same ranges as above
+// 20 xx Drum Filter Cutoff Freq same ranges as above
+// xx = drum MIDI key number
+// 21 xx Drum Filter Resonance same ranges as above
+// xx = drum MIDI key number
+// 22 xx Drum EG Attack Rage same ranges as above
+// xx = drum MIDI key number
+// 23 xx Drum EG Decay Rate same ranges as above
+// xx = drum MIDI key number
+// 24 xx Drum Pitch Coarse same ranges as above
+// xx = drum MIDI key number
+// 25 xx Drum Pitch Fine same ranges as above
+// xx = drum MIDI key number
+// 26 xx Drum Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 28 xx Drum Pan Random, Left..Center..Right
+// 0.......1.....64......127 MIDI data range
+// xx = drum MIDI key number
+// 29 xx Drum Reverb Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 30 xx Drum Chorus Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 31 xx Drum Variation Send Level 0..64..127 MIDI data range
+// xx = drum MIDI key number
+// 127 127 Null RPN (disables RPN/NRPN parameters from being altered).
+//
+//
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb,
+ int data_msb, int data_lsb) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ data_msb = nrpn_msb & 0x7f;
+ data_lsb = nrpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // now that the NRPN state is set, send the NRPN data values
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ status &= cont(channel, 38, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, int data_msb) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ data_msb = nrpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // now that the NRPN state is set, send the NRPN data value,
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::NRPN(int channel, int nrpn_msb, int nrpn_lsb, double data) {
+ channel = channel & 0x0f;
+ nrpn_msb = nrpn_msb & 0x7f;
+ nrpn_lsb = nrpn_msb & 0x7f;
+ if (data < -1.0) {
+ data = -1.0;
+ } else if (data > 1.0) {
+ data = 1.0;
+ }
+
+ int status = 1;
+
+ // check to see if the nrpn_msb and nrpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != nrpn_msb) {
+ status &= cont(channel, 99, nrpn_msb);
+ rpn_msb_status[getPort()][channel] = nrpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != nrpn_lsb) {
+ status &= cont(channel, 98, nrpn_lsb);
+ rpn_lsb_status[getPort()][channel] = nrpn_lsb;
+ }
+
+ // convert data into 14 bit number
+ int data14 = (int)((data+1.0)/2.0*16383 + 0.5);
+
+ // send the NRPN data values, two message of 7 bits each
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (nrpn_msb != 127 && nrpn_lsb != 127) {
+ status &= cont(channel, 6, data14 >> 7);
+ status &= cont(channel, 38, data14 & 0x7f);
+ }
+
+ return status;
+}
+
+
+//////////
+//
+// Convenience functions for use of NRPN function. Note that these
+// are "Non-Registered" Parameter Numbers which means that each
+// synthesizer manufacture can do whatever they want, so these
+// functions might not behave the way you expect them to do so.
+// Yamaha XG and Roland GS NRPN specifications are given below.
+//
+
+int MidiOutput::NRPN_null(int channel) {
+ return NRPN(channel, 127, 127, 0);
+}
+
+int MidiOutput::NRPN_vibratoRate(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 8, value+64);
+}
+
+int MidiOutput::NRPN_vibratoRate(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 8, value);
+}
+
+int MidiOutput::NRPN_vibratoDepth(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 9, value+64);
+}
+
+int MidiOutput::NRPN_vibratoDepth(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 9, value);
+}
+
+int MidiOutput::NRPN_vibratoDelay(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 32, value+64);
+}
+
+int MidiOutput::NRPN_vibratoDelay(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 32, value);
+}
+
+int MidiOutput::NRPN_filterCutoff(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 33, value+64);
+}
+
+int MidiOutput::NRPN_filterCutoff(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 33, value);
+}
+
+int MidiOutput::NRPN_attack(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 99, value+64);
+}
+
+int MidiOutput::NRPN_attack(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 99, value);
+}
+
+int MidiOutput::NRPN_decay(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 100, value+64);
+}
+
+int MidiOutput::NRPN_decay(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 100, value);
+}
+
+int MidiOutput::NRPN_release(int channel, int value) {
+ // value in range -64..+63
+ return NRPN(channel, 1, 102, value+64);
+}
+
+int MidiOutput::NRPN_release(int channel, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(channel, 1, 102, value);
+}
+
+int MidiOutput::NRPN_drumFilterCutoff(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 20, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumFilterCutoff(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 20, drum, value);
+}
+
+int MidiOutput::NRPN_drumFilterResonance(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 21, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumFilterResonance(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 21, drum, value);
+}
+
+int MidiOutput::NRPN_drumAttack(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 22, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumAttack(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 22, drum, value);
+}
+
+int MidiOutput::NRPN_drumDecay(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 23, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumDecay(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 23, drum, value);
+}
+
+int MidiOutput::NRPN_drumPitch(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 24, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumPitch(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 24, drum, value);
+}
+
+int MidiOutput::NRPN_drumLevel(int drum, int value) {
+ // value in range -64..+63
+ return NRPN(9, 26, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumLevel(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 26, drum, value);
+}
+
+int MidiOutput::NRPN_drumPan(int drum, int value) {
+ return NRPN(9, 28, drum, value+64);
+}
+
+int MidiOutput::NRPN_drumPan(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 28, drum, value);
+}
+
+int MidiOutput::NRPN_drumReverb(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 29, drum, value);
+}
+
+int MidiOutput::NRPN_drumReverb(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 29, drum, value);
+}
+
+int MidiOutput::NRPN_drumChorus(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 30, drum, value);
+}
+
+int MidiOutput::NRPN_drumChorus(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 30, drum, value);
+}
+
+int MidiOutput::NRPN_drumVariation(int drum, int value) {
+ // note offset from 0 not -64
+ return NRPN(9, 31, drum, value);
+}
+
+int MidiOutput::NRPN_drumVariation(int drum, double value) {
+ // value in range -1.0..+1.0
+ return NRPN(9, 31, drum, value);
+}
+
+//
+// Convenience functions for use of NRPN function.
+//
+//////////
+
+
+
+//////////////////////////////
+//
+// RPN -- sends a registered parameter number where:
+// parameter #1: channel (0-15)
+// parameter #2: RPN MSB indicator (controller #101 data)
+// parameter #3: RPN LSB indicator (controller #100 data)
+// parameter #4: RPN MSB data (controller #6 data)
+// [parameter #5: RPN LSB data (controller #38 data)]
+// or:
+// parameter #1: channel (0-15)
+// parameter #2: NRPN MSB indicator (controller #99 data)
+// parameter #3: NRPN LSB indicator (controller #98 data)
+// parameter #4: NRPN Floating point in range (-1..1) (ccont#6 and #38 data)
+//
+//
+// RPN (registered parameter number) -- General MIDI and
+// Extended MIDI mess. It becomes the receiving synthesizer's
+// responsibility to determine the meaning of continuous
+// controller (ccont) #6 from data sent with cconts #100,101 (for
+// RPNS) and cconts #98,99 (for NRPNS).
+//
+// The data for RPNs are transfered to synthesizer with
+// data slider ccont #6(MSB) and ccont #38(LSB). Also data increment
+// ccont#96 (data increment) and ccont#97 (data decrement) are in
+// relation to the RPN or NRPN in effect. Increment and Decrement
+// are not recommend to use with RPN's because of confusion in the
+// MIDI industry over which 7-bit data (#6 or #38) to increment.
+//
+// Once you have selected an RPN on a given channel, the
+// channel will apply subsequent Data Entry to the
+// selected parameter. After making the necessary settings
+// you should set RPN's to NULL to reduce the risk of
+// operational errors. a NULL RPN will disable the previous
+// values of either RPN or NRPN data.
+//
+// The following RPN values are registered:
+// CCont #100 = LSB of RPN parameter ID
+// CCont #101 = MSB of RPN parameter ID
+//
+// RPN Data Range
+// MSB LSB Parameter (ccont#6=MSB, ccont#38=LSB)
+// === ===== ====================== ======================
+
+// 0 0 Pitchbend Sensitivity 0-127 (default 2) (LSB ignored)
+// (The number of +/- half steps in
+// pitch wheel range).
+// 0 1 Fine Tune -64.. 0..+63 logical range
+// 0..64..127 MIDI data range
+// 0 2 Coarse Tune same range as above.
+// 0 3 Change Tuning Program 0..127
+// 0 4 Change Tuning Bank 0..127
+//
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb,
+ int data_msb, int data_lsb) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ data_msb = rpn_msb & 0x7f;
+ data_lsb = rpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // now that the RPN state is set, send the RPN data values
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ status &= cont(channel, 38, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, int data_msb) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ data_msb = rpn_msb & 0x7f;
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // now that the RPN state is set, send the RPN data value,
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data_msb);
+ }
+
+ return status;
+}
+
+
+int MidiOutput::RPN(int channel, int rpn_msb, int rpn_lsb, double data) {
+ channel = channel & 0x0f;
+ rpn_msb = rpn_msb & 0x7f;
+ rpn_lsb = rpn_msb & 0x7f;
+ if (data < -1.0) {
+ data = -1.0;
+ } else if (data > 1.0) {
+ data = 1.0;
+ }
+
+ int status = 1;
+
+ // check to see if the rpn_msb and rpn_lsb are the same
+ // as the last call to this function, if not, then send
+ // the appropriate MIDI controller values.
+ if (rpn_msb_status[getPort()][channel] != rpn_msb) {
+ status &= cont(channel, 101, rpn_msb);
+ rpn_msb_status[getPort()][channel] = rpn_msb;
+ }
+ if (rpn_lsb_status[getPort()][channel] != rpn_lsb) {
+ status &= cont(channel, 100, rpn_lsb);
+ rpn_lsb_status[getPort()][channel] = rpn_lsb;
+ }
+
+ // convert data into 14 bit number
+ int data14 = (int)((data+1.0)/2.0*16383 + 0.5);
+
+ // send the RPN data values, two message of 7 bits each
+ // but do not bother sending any data if the Null RPN is in effect.
+ if (rpn_msb != 127 && rpn_lsb != 127) {
+ status &= cont(channel, 6, data14 >> 7);
+ status &= cont(channel, 38, data14 & 0x7f);
+ }
+
+ return status;
+}
+
+
+//////////
+//
+// Convenience functions for use of RPN function.
+//
+
+int MidiOutput::RPN_null(void) {
+ int status = 1;
+ for (int i=0; i<16; i++) {
+ status &= RPN_null(i);
+ }
+ return status;
+}
+
+int MidiOutput::RPN_null(int channel) {
+ return RPN(channel, 127, 127, 0);
+}
+
+int MidiOutput::pbRange(int channel, int steps) {
+ // default value for pitch bend sensitivity is 2 semitones.
+ return RPN(channel, 0, 0, steps);
+}
+
+int MidiOutput::tuneFine(int channel, int cents) {
+ // data from -64 to + 63
+ return RPN(channel, 0, 1, cents+64);
+}
+
+int MidiOutput::fineTune(int channel, int cents) {
+ return tuneFine(channel, cents);
+}
+
+int MidiOutput::tuneCoarse(int channel, int steps) {
+ // data from -64 to + 63
+ return RPN(channel, 0, 1, steps+64);
+}
+
+int MidiOutput::coarseTune(int channel, int steps) {
+ return tuneCoarse(channel, steps);
+}
+
+int MidiOutput::tuningProgram(int channel, int program) {
+ return RPN(channel, 0, 3, program);
+}
+
+int MidiOutput::tuningBank(int channel, int bank) {
+ return RPN(channel, 0, 4, bank);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// MidiOutput::initializeRPN -- set up the RPN status arrays
+// ignores initiaization request if already initialized.
+//
+
+void MidiOutput::initializeRPN(void) {
+ int i, channel;
+
+ if (rpn_lsb_status == NULL) {
+ rpn_lsb_status = new Array<int>[getNumPorts()];
+ for (i=0; i<getNumPorts(); i++) {
+ rpn_lsb_status[i].setSize(16);
+ rpn_lsb_status[i].allowGrowth(0);
+ for (channel=0; channel<16; channel++) {
+ rpn_lsb_status[i][channel] = 127;
+ }
+ }
+ }
+
+ if (rpn_msb_status == NULL) {
+ rpn_msb_status = new Array<int>[getNumPorts()];
+ for (i=0; i<getNumPorts(); i++) {
+ rpn_msb_status[i].setSize(16);
+ rpn_msb_status[i].allowGrowth(0);
+ for (channel=0; channel<16; channel++) {
+ rpn_msb_status[i][channel] = 127;
+ }
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::deinitializeRPN -- destroy the RPN status arrays
+// do nothing if the arrays are not initialized
+//
+
+void MidiOutput::deinitializeRPN(void) {
+ if (rpn_msb_status != NULL) {
+ delete [] rpn_msb_status;
+ rpn_msb_status = NULL;
+ }
+
+ if (rpn_msb_status != NULL) {
+ delete [] rpn_msb_status;
+ rpn_msb_status = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputAscii
+//
+
+void MidiOutput::writeOutputAscii(int command, int p1, int p2) {
+ outputRecordFile << std::dec;
+ outputRecordFile.width(6);
+ outputRecordFile << (timer.getTime()-lastFlushTime) <<'\t';
+ outputRecordFile << "0x" << std::hex;
+ outputRecordFile.width(2);
+ outputRecordFile << command << ' ';
+ outputRecordFile << std::dec;
+ outputRecordFile.width(3);
+ outputRecordFile << p1 << ' ';
+ outputRecordFile << std::dec;
+ outputRecordFile.width(3);
+ outputRecordFile<< p2;
+ outputRecordFile << std::endl;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputBinary
+//
+
+void MidiOutput::writeOutputBinary(int command, int p1, int p2) {
+ // don't store 0xf8 command since it will be used to mark the end of the
+ if (command == 0xf8) return;
+
+ // write the delta time (four bytes)
+ outputRecordFile.writeBigEndian((ulong)(timer.getTime() - lastFlushTime));
+
+ // write midi data
+ // don't store 0xf8 command since it will be used to mark the end of the
+ // delta time data.
+ outputRecordFile << (uchar)p1;
+ outputRecordFile << (uchar)p2;
+ outputRecordFile << (uchar)0xf8;
+}
+
+
+
+//////////////////////////////
+//
+// MidiOutput::writeOutputMidifile
+//
+
+void MidiOutput::writeOutputMidifile(int command, int p1, int p2) {
+ // not yet implemented
+}
+
+
+
+// md5sum: 1c518e5130ac9ba0d79c4e9ce7fa41cf - MidiOutput.cpp =css= 20030102
diff --git a/src/midiio/src/MidiPort.cpp b/src/midiio/src/MidiPort.cpp
new file mode 100644
index 0000000..1a03dac
--- /dev/null
+++ b/src/midiio/src/MidiPort.cpp
@@ -0,0 +1,189 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: 21 December 1997
+// Last Modified: Fri Jan 23 10:24:35 GMT-0800 1998
+// Filename: .../sig/code/control/MidiPort/MidiPort.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/MidiPort.cpp
+// Syntax: C++
+//
+// Description: A unified object that handles basic MIDI input and output.
+// Derived from the MidiInPort and MidiOutPort classes.
+//
+
+#include "MidiPort.h"
+
+
+//////////////////////////////
+//
+// MidiPort::MidiPort
+//
+
+MidiPort::MidiPort(void) : MidiOutPort(), MidiInPort() {
+ // nothing
+}
+
+
+MidiPort::MidiPort(int outputPort, int inputPort) :
+ MidiOutPort(outputPort), MidiInPort(inputPort) {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::~MidiPort
+//
+
+MidiPort::~MidiPort() {
+ // nothing
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getChannelInOffset -- return the MIDI channel offset of
+// the MIDI input.
+//
+
+int MidiPort::getChannelInOffset(void) const {
+ return MidiInPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getChannelOutOffset -- return the MIDI channel offset of
+// the MIDI output.
+//
+
+int MidiPort::getChannelOutOffset (void) const {
+ return MidiOutPort::getChannelOffset();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getInputPort
+//
+
+int MidiPort::getInputPort(void) {
+ return MidiInPort::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getInputTrace
+//
+
+int MidiPort::getInputTrace(void) {
+ return MidiInPort::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getOutputPort
+//
+
+int MidiPort::getOutputPort(void) {
+ return MidiOutPort::getPort();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::getOutputTrace
+//
+
+int MidiPort::getOutputTrace(void) {
+ return MidiOutPort::getTrace();
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setChannelOffset -- sets the MIDI channel offset
+//
+
+void MidiPort::setChannelOffset(int anOffset) {
+ MidiInPort::setChannelOffset(anOffset);
+ MidiOutPort::setChannelOffset(anOffset);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setInputPort
+//
+
+void MidiPort::setInputPort(int aPort) {
+ MidiInPort::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setInputTrace
+//
+
+int MidiPort::setInputTrace(int aState) {
+ return MidiInPort::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setOutputPort
+//
+
+void MidiPort::setOutputPort(int aPort) {
+ MidiOutPort::setPort(aPort);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::setOutputTrace
+//
+
+int MidiPort::setOutputTrace(int aState) {
+ return MidiOutPort::setTrace(aState);
+}
+
+
+
+//////////////////////////////
+//
+// MidiPort::toggleInputTrace
+//
+
+void MidiPort::toggleInputTrace(void) {
+ MidiInPort::toggleTrace();
+}
+
+
+//////////////////////////////
+//
+// MidiPort::toggleOutputTrace
+//
+
+void MidiPort::toggleOutputTrace(void) {
+ MidiOutPort::toggleTrace();
+}
+
+
+
+// md5sum: c2583f3ed21e238ba6b298915cb728aa - MidiPort.cpp =css= 20030102
diff --git a/src/midiio/src/Options.cpp b/src/midiio/src/Options.cpp
new file mode 100644
index 0000000..0341fe3
--- /dev/null
+++ b/src/midiio/src/Options.cpp
@@ -0,0 +1,887 @@
+//
+// Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sat Mar 27 18:17:06 PST 1999
+// Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function)
+// Last Modified: Fri May 5 17:52:01 PDT 2000 (added --options suppression)
+// Last Modified: Tue May 1 01:25:58 PDT 2001 (fixed getArgumentCount())
+// Filename: ...sig/maint/code/sigBase/Options.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Options.cpp
+// Documentation: http://sig.sapp.org/doc/classes/Options
+// Syntax: C++
+//
+// Description: Handles command-line options in a graceful manner.
+//
+
+int optionListCompare(const void* a, const void* b);
+
+#include "Options.h"
+#include "Options_private.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <iostream>
+
+
+//////////////////////////////
+//
+// Options::Options --
+//
+
+Options::Options(void) {
+ optionFlag = '-';
+ gargc = -1;
+ gargv = NULL;
+ argument.setSize(0);
+ argument.allowGrowth();
+ optionRegister.setSize(0);
+ optionRegister.allowGrowth();
+ optionList.setSize(0);
+ optionList.allowGrowth();
+ processedQ = 0;
+ sortedQ = 0;
+ commandString = NULL;
+ options_error_check = 1;
+ suppressQ = 0;
+ optionsArgument = 0;
+}
+
+
+Options::Options(int argc, char** argv) {
+ optionFlag = '-';
+ gargc = -1;
+ gargv = NULL;
+ argument.setSize(0);
+ argument.allowGrowth();
+ optionRegister.setSize(0);
+ optionRegister.allowGrowth();
+ optionList.setSize(0);
+ optionList.allowGrowth();
+ processedQ = 0;
+ sortedQ = 0;
+ commandString = NULL;
+ options_error_check = 1;
+ suppressQ = 0;
+ optionsArgument = 0;
+
+ setOptions(argc, argv);
+}
+
+
+
+//////////////////////////////
+//
+// Options::~Options --
+//
+
+Options::~Options() {
+ reset();
+}
+
+
+
+//////////////////////////////
+//
+// Options::argc -- returns the argument count as from main().
+//
+
+int Options::argc(void) const {
+ return gargc;
+}
+
+
+
+//////////////////////////////
+//
+// Options::argv -- returns the arguments strings as from main().
+//
+
+char** Options::argv(void) const {
+ return gargv;
+}
+
+
+
+//////////////////////////////
+//
+// Options::define -- define an option entry in the option register
+//
+
+void Options::define(const char* aDefinition) {
+ sortedQ = 0; // have to sort option list later
+ option_register* definitionEntry;
+ option_list* optionListEntry;
+
+
+ // error if the definition string doesn't contain an equals sign.
+ if (strchr(aDefinition, '=') == NULL) {
+ std::cout << "Error: no \"=\" in option definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // get the length of the definition string
+ int len = strlen(aDefinition);
+
+ // put space before and after the equals sign so that strtok works
+ char* definitionString;
+ definitionString = new char[len + 3];
+ int i = 0;
+ while (aDefinition[i] != '=' && i < len) {
+ definitionString[i] = aDefinition[i];
+ i++;
+ }
+ definitionString[i] = ' ';
+ i++;
+ definitionString[i] = '=';
+ i++;
+ definitionString[i] = ' ';
+ for (int k=i; k<len+2; k++) {
+ definitionString[k+1] = aDefinition[k-1];
+ }
+ len += 2;
+
+ // determine the registry index for the definition
+ int definitionIndex = optionRegister.getSize();
+
+
+ // set up space for a definition entry
+ definitionEntry = new option_register(aDefinition, OPTION_UNKNOWN_TYPE,
+ "", NULL);
+
+
+ char *tempstr; // temporary storage for strtok use on defaultString
+ tempstr = new char[len + 1];
+ strncpy(tempstr, definitionString, len);
+
+ char *optionName; // option name to add to list
+
+ // get the first option name
+ optionName = strtok(tempstr, " \t\n|");
+ if (optionName[0] == '=') {
+ std::cout << "Error: must specify an option name in definition: "
+ << aDefinition << std::endl;
+ exit(1);
+ }
+ // store an entry for each option name alias
+ const char* tempsearch;
+ while (optionName != NULL && optionName[0] != '=') {
+ tempsearch = getDefinition(optionName);
+ if (tempsearch != NULL) {
+ std::cerr << "option name \"" << optionName
+ << "\" from definition: " << aDefinition << std::endl;
+ std::cerr << "is already defined in definition: "
+ << tempsearch << std::endl;
+ exit(1);
+ }
+ optionListEntry = new option_list(optionName, definitionIndex);
+ optionList.append(optionListEntry);
+ optionName = strtok(NULL, " \t\n|");
+ }
+ if (optionName == NULL) {
+ std::cout << "Error: unknown error in definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // now process the option type and any default value.
+ i = 0;
+
+ // find the equals sign
+ while (definitionString[i] != '=' && i < len) {
+ i++;
+ }
+ i++;
+ // skip over any white space
+ while (isspace(definitionString[i]) && i < len) {
+ i++;
+ }
+
+ // this character must be the option type
+ char optionType = (char)tolower(definitionString[i]);
+ definitionEntry->setType(optionType);
+ i++;
+
+
+ // check to make sure that the type is correct.
+ if (optionType != OPTION_STRING_TYPE &&
+ optionType != OPTION_INT_TYPE &&
+ optionType != OPTION_FLOAT_TYPE &&
+ optionType != OPTION_DOUBLE_TYPE &&
+ optionType != OPTION_BOOLEAN_TYPE &&
+ optionType != OPTION_CHAR_TYPE ) {
+ std::cout << "Error: unknown option type \'" << optionType
+ << "\' in defintion: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+ // skip any white space after option type.
+ while (isspace(definitionString[i]) && i < len) {
+ i++;
+ }
+
+
+ // there can only be two characters now: '\0' or ':'
+ if (i >= len || definitionString[i] == '\0') {
+ goto option_finish;
+ } else if (i<len && definitionString[i] == ':') {
+ i++;
+ } else {
+ std::cout << "Unknown error in definition: " << aDefinition << std::endl;
+ exit(1);
+ }
+
+
+ // now proces the default string. store it in a temp storage for copying
+
+ // skip any white space after option type.
+ while (i < len && isspace(definitionString[i])) {
+ i++;
+ }
+ if (i >= len || definitionString[i] == '\0') {
+ goto option_finish;
+ }
+
+
+ // now at beginnng of default option string which continues
+ // until the end of the definition string.
+ definitionEntry->setDefault(&definitionString[i]);
+
+option_finish:
+
+ optionRegister.append(definitionEntry);
+
+
+ delete [] definitionString;
+ delete [] tempstr;
+
+}
+
+
+void Options::define(const char* aDefinition, const char* description) {
+ define(aDefinition);
+
+ // now find some place to store the description...
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArg -- returns the specified argument.
+// argurment 0 is the command name.
+//
+
+char* Options::getArg(int index) {
+ if (index < 0 || index >= argument.getSize()) {
+ std::cout << "Error: argument " << index << " does not exist." << std::endl;
+ exit(1);
+ }
+ return argument[index];
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgument -- same as getArg
+//
+
+char* Options::getArgument(int index) {
+ return getArg(index);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgCount -- number of arguments on command line.
+// does not count the options or the command name.
+//
+
+int Options::getArgCount(void) {
+ return argument.getSize() - 1;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getArgumentCount -- Same as getArgCount().
+//
+
+int Options::getArgumentCount(void) {
+ return getArgCount();
+}
+
+
+
+//////////////////////////////
+//
+// Options::getBoolean -- returns true if the option was
+// used on the command line.
+//
+
+int Options::getBoolean(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return 0;
+ }
+ if (optionRegister[index]->getModifiedQ() == 1) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::getCommand -- returns argv[0]
+//
+
+const char* Options::getCommand(void) {
+ if (argument.getSize() == 0) {
+ return "";
+ } else {
+ return argument[0];
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::getCommandLine -- returns a string which contains the
+// command-line call to the program.
+//
+
+const char* Options::getCommandLine(void) {
+ if (commandString != NULL) {
+ return commandString;
+ }
+
+ int length = 0;
+ int i;
+ for (i=0; i<gargc; i++) {
+ length += strlen(gargv[i]) + 1;
+ }
+ length--; // remove the last space
+ commandString = new char[length + 1];
+ strcpy(commandString, gargv[0]);
+ for (i=1; i<gargc; i++) {
+ strcat(commandString, " ");
+ strcat(commandString, gargv[i]);
+ }
+
+ return commandString;
+}
+
+
+
+
+//////////////////////////////
+//
+// Options::getDefinition -- returns the definition
+// for the specified option name. Returns NULL
+// if there is no entry for the option name.
+// It is assumed that the option list is unsorted.
+// spaces count in the input option name.
+//
+
+const char* Options::getDefinition(const char* optionName) {
+ int i;
+ for (i=0; i<optionList.getSize(); i++) {
+ if (strcmp(optionName, optionList[i]->getName()) == 0) {
+ return optionRegister[optionList[i]->getIndex()]->getDefinition();
+ }
+ }
+ return (const char*)NULL;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getDouble -- returns the double float associated
+// with the given option. Returns 0 if there is no
+// number associated with the option.
+//
+
+double Options::getDouble(const char* optionName) {
+ return strtod(getString(optionName), (char**)NULL);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getFlag --
+//
+
+char Options::getFlag(void) {
+ return optionFlag;
+}
+
+
+
+//////////////////////////////
+//
+// Options::getFloat -- returns the floating point number
+// associated with the given option.
+//
+
+float Options::getFloat(const char* optionName) {
+ return (float)getDouble(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getInt -- returns the integer argument. Can handle
+// hexadecimal, decimal, and octal written in standard
+// C syntax.
+//
+
+int Options::getInt(const char* optionName) {
+ return (int)strtol(getString(optionName), (char**)NULL, 0);
+}
+
+int Options::getInteger(const char* optionName) {
+ return getInt(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// Options::getString --
+//
+
+const char* Options::getString(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return "UNKNOWN OPTION";
+ } else {
+ return optionRegister[index]->getOption();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::optionsArg -- returns true if the --options is present
+// on the command line, otherwise returns false.
+//
+
+int Options::optionsArg(void) {
+ return optionsArgument;
+}
+
+
+
+//////////////////////////////
+//
+// Options::print --
+//
+
+void Options::print(void) {
+ for (int i=0; i<optionRegister.getSize(); i++) {
+ std::cout << optionRegister[i]->getDefinition() << std::endl;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::reset --
+//
+
+void Options::reset(void) {
+ int i;
+ for (i=0; i<optionRegister.getSize(); i++) {
+ delete optionRegister[i];
+ }
+ optionRegister.setSize(0);
+ for (i=0; i<optionList.getSize(); i++) {
+ delete optionList[i];
+ }
+ optionList.setSize(0);
+ for (i=0; i<argument.getSize(); i++) {
+ delete [] argument[i];
+ }
+ argument.setSize(0);
+
+ if (commandString != NULL) {
+ delete [] commandString;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::setFlag -- set the character used to indicate an
+// option. For unix this is usually '-', in MS-DOS,
+// this is usually '/'; But the syntax of the Options
+// class is for Unix-style options.
+//
+
+void Options::setFlag(char aFlag) {
+ optionFlag = aFlag;
+}
+
+
+
+
+//////////////////////////////
+//
+// setModified --
+//
+
+void Options::setModified(const char* optionName, const char* aString) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return;
+ }
+
+ optionRegister[getRegIndex(optionName)]->setModified(aString);
+}
+
+
+
+
+//////////////////////////////
+//
+// setOptions --
+//
+
+void Options::setOptions(int argc, char** argv) {
+ processedQ = 0;
+
+ gargc = argc;
+ gargv = argv;
+}
+
+
+
+//////////////////////////////
+//
+// Options:getType -- returns the type of the option
+//
+
+char Options::getType(const char* optionName) {
+ int index = getRegIndex(optionName);
+ if (index < 0) {
+ return -1;
+ } else {
+ return optionRegister[getRegIndex(optionName)]->getType();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Options::process -- same as verify
+// default values: error_check = 1, suppress = 0;
+//
+
+void Options::process(int argc, char** argv, int error_check, int suppress) {
+ setOptions(argc, argv);
+ verify(error_check, suppress);
+}
+
+
+void Options::process(int error_check, int suppress) {
+ verify(error_check, suppress);
+}
+
+
+
+//////////////////////////////
+//
+// Options::verify --
+// default value: error_check = 1, suppress = 0;
+//
+
+void Options::verify(int error_check, int suppress) {
+ options_error_check = error_check;
+ int gargp = 1;
+ int optionend = 0;
+
+ if (suppress) {
+ suppressQ = 1;
+ } else {
+ suppressQ = 0;
+ }
+
+ // if calling verify again, must remove previous argument list.
+ if (argument.getSize() != 0) {
+ for (int j=0; j<argument.getSize(); j++) {
+ delete argument[j];
+ }
+ argument.setSize(0);
+ }
+
+ char* tempargument;
+ tempargument = new char[strlen(gargv[0])+1];
+ strcpy(tempargument, gargv[0]);
+ argument.append(tempargument);
+
+ int oldgargp;
+ int position = 0;
+ int running = 0;
+ while (gargp < gargc && optionend == 0) {
+ if (optionQ(gargv[gargp], gargp)) {
+ oldgargp = gargp;
+ gargp = storeOption(gargp, position, running);
+ if (gargp != oldgargp) {
+ running = 0;
+ position = 0;
+ }
+ } else {
+ if ( strlen(gargv[gargp]) == 2 && gargv[gargp][0] == getFlag() &&
+ gargv[gargp][2] == getFlag() ) {
+ optionend = 1;
+ gargp++;
+ break;
+ } else { // this is an argument
+ tempargument = new char[strlen(gargv[gargp])+1];
+ strcpy(tempargument, gargv[gargp]);
+ argument.append(tempargument);
+ gargp++;
+ }
+ }
+ }
+
+ while (gargp < gargc) {
+ tempargument = new char[strlen(gargv[gargp])+1];
+ strcpy(tempargument, gargv[gargp]);
+ argument.append(tempargument);
+ gargp++;
+ }
+
+}
+
+
+void Options::verify(int argc, char** argv, int error_check, int suppress) {
+ setOptions(argc, argv);
+ verify(error_check, suppress);
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+
+//////////////////////////////
+//
+// getRegIndex -- returns the index of the option associated
+// with this name.
+//
+
+int Options::getRegIndex(const char* optionName) {
+ if (suppressQ && strcmp("options", optionName) == 0) {
+ return -1;
+ }
+
+ if (sortedQ == 0) {
+ sortOptionNames();
+ }
+ option_list key(optionName, -1);
+ option_list* keyp = &key;
+ void* searchresult;
+ searchresult = bsearch(&keyp, optionList.getBase(),
+ optionList.getSize(), sizeof(option_list*), optionListCompare);
+ if (searchresult != NULL) {
+ return (*((option_list**)searchresult))->getIndex();
+ } else if (strcmp("options", optionName) == 0) {
+ print();
+ exit(1);
+ }
+
+ if (options_error_check) {
+ std::cout << "Error: unknown option \"" << optionName << "\"." << std::endl;
+ print();
+ exit(1);
+ }
+
+ return -1;
+}
+
+
+
+//////////////////////////////
+//
+// optionQ -- returns true if the string is an option
+// "--" is not an option, also '-' is not an option.
+// aString is assumed to not be NULL.
+//
+
+int Options::optionQ(const char* aString, int& argp) {
+ if (aString[0] == getFlag()) {
+ if (aString[1] == '\0') {
+ argp++;
+ return 0;
+ } else if (aString[1] == getFlag()) {
+ if (aString[2] == '\0') {
+ argp++;
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+}
+
+
+
+
+//////////////////////////////
+//
+// sortOptionNames --
+//
+
+void Options::sortOptionNames(void) {
+ qsort(optionList.getBase(), optionList.getSize(),
+ sizeof(option_list*), optionListCompare);
+ sortedQ = 1;
+}
+
+
+
+//////////////////////////////
+//
+// storeOption --
+//
+
+#define OPTION_FORM_SHORT 0
+#define OPTION_FORM_LONG 1
+#define OPTION_FORM_CONTINUE 2
+
+int Options::storeOption(int gargp, int& position, int& running) {
+ int optionForm;
+ char tempname[1024];
+ char optionType = '\0';
+
+ if (running) {
+ optionForm = OPTION_FORM_CONTINUE;
+ } else if (gargv[gargp][1] == getFlag()) {
+ optionForm = OPTION_FORM_LONG;
+ } else {
+ optionForm = OPTION_FORM_SHORT;
+ }
+
+ switch (optionForm) {
+ case OPTION_FORM_CONTINUE:
+ position++;
+ tempname[0] = gargv[gargp][position];
+ tempname[1] = '\0';
+ optionType = getType(tempname);
+ if (optionType != OPTION_BOOLEAN_TYPE) {
+ running = 0;
+ position++;
+ }
+ break;
+ case OPTION_FORM_SHORT:
+ position = 1;
+ tempname[0] = gargv[gargp][position];
+ tempname[1] = '\0';
+ optionType = getType(tempname);
+ if (optionType != OPTION_BOOLEAN_TYPE) {
+ position++;
+ }
+ break;
+ case OPTION_FORM_LONG:
+ position = 2;
+ while (gargv[gargp][position] != '=' &&
+ gargv[gargp][position] != '\0') {
+ tempname[position-2] = gargv[gargp][position];
+ position++;
+ }
+ tempname[position-2] = '\0';
+ optionType = getType(tempname);
+ if (optionType == -1) { // suppressed --options option
+ optionsArgument = 1;
+ break;
+ }
+ if (gargv[gargp][position] == '=') {
+ if (optionType == OPTION_BOOLEAN_TYPE) {
+ std::cout << "Error: boolean variable cannot have any options: "
+ << tempname << std::endl;
+ exit(1);
+ }
+ position++;
+ }
+ break;
+ }
+
+ if (optionType == -1) { // suppressed --options option
+ optionsArgument = 1;
+ gargp++;
+ position = 0;
+ return gargp;
+ }
+
+ if (gargv[gargp][position] == '\0' &&
+ optionType != OPTION_BOOLEAN_TYPE) {
+ gargp++;
+ position = 0;
+ }
+
+ if (optionForm != OPTION_FORM_LONG && optionType == OPTION_BOOLEAN_TYPE &&
+ gargv[gargp][position+1] != '\0') {
+ running = 1;
+ } else if (optionType == OPTION_BOOLEAN_TYPE &&
+ gargv[gargp][position+1] == '\0') {
+ running = 0;
+ }
+
+ if (gargp >= gargc) {
+ std::cout << "Error: last option requires a parameter" << std::endl;
+ exit(1);
+ }
+ setModified(tempname, &gargv[gargp][position]);
+
+ if (!running) {
+ gargp++;
+ }
+ return gargp;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// helping function
+//
+
+//////////////////////////////
+//
+// optionListCompare -- for sorting the option list
+//
+
+int optionListCompare(const void* a, const void* b) {
+//cerr << " comparing: " << (*((option_list**)a))->getName()
+// << " i=" << (*((option_list**)a))->getIndex()
+// << " :to: "
+// << (*((option_list**)b))->getName()
+// << " i=" << (*((option_list**)b))->getIndex() << std::endl;
+ return strcmp((*((option_list**)a))->getName(),
+ (*((option_list**)b))->getName());
+}
+
+
+
+// md5sum: 63584ffabc92170fdb9ef5caedb5a3f6 - Options.cpp =css= 20030102
diff --git a/src/midiio/src/Options_private.cpp b/src/midiio/src/Options_private.cpp
new file mode 100644
index 0000000..5a875a8
--- /dev/null
+++ b/src/midiio/src/Options_private.cpp
@@ -0,0 +1,358 @@
+//
+// Copyright 1998-1999 by Craig Stuart Sapp, All Rights Reserved.
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Apr 5 13:07:18 PDT 1998
+// Last Modified: Sun Jan 10 05:43:24 PST 1999
+// Filename: ...sig/maint/code/sigBase/Options_private.cpp
+// Web Address: http://sig.sapp.org/src/sigBase/Options_private.cpp
+// Syntax: C++
+//
+// Description: A private set of functions for use in the Options class.
+//
+
+#include "Options_private.h"
+#include <iostream>
+#include <stdlib.h>
+#include <string.h>
+
+
+//////////////////////////////
+//
+// option_register::option_register --
+//
+
+option_register::option_register(void) {
+ definition = NULL;
+ defaultOption = NULL;
+ modifiedOption = NULL;
+ type = 's';
+}
+
+
+option_register::option_register(const char* aDefinition, char aType,
+ const char* aDefaultOption, const char* aModifiedOption) {
+ definition = NULL;
+ defaultOption = NULL;
+ modifiedOption = NULL;
+
+ setType(aType);
+ setDefinition(aDefinition);
+ setDefault(aDefaultOption);
+ setModified(aModifiedOption);
+}
+
+
+
+//////////////////////////////
+//
+// option_register::~option_register --
+//
+
+option_register::~option_register() {
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ definition = NULL;
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ defaultOption = NULL;
+
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::clearModified -- sets the modified string to
+// NULL.
+//
+
+void option_register::clearModified(void) {
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getDefinition -- returns the initial definition
+// string used to define this entry.
+//
+
+const char* option_register::getDefinition(void) {
+ return definition;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getDefault -- returns the default string
+// to be returned. Will never return a NULL;
+//
+
+const char* option_register::getDefault(void) {
+ return defaultOption;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getModified -- return the modified
+// option string
+//
+
+const char* option_register::getModified(void) {
+ return modifiedOption;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getModifiedQ -- returns true if
+// modified string is not null, false otherwise.
+//
+
+int option_register::getModifiedQ(void) {
+ if (modifiedOption == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getType --
+//
+
+char option_register::getType(void) {
+ return type;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::getOption -- return the modified option
+// or the default option if no modified option.
+//
+
+const char* option_register::getOption(void) {
+ if (getModifiedQ()) {
+ return getModified();
+ } else {
+ return getDefault();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::reset -- deallocate space for all
+// strings in object. (but default string is set to "")
+//
+
+void option_register::reset(void) {
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ definition = NULL;
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ defaultOption = NULL;
+ defaultOption = new char[1];
+ defaultOption[0] = '\0';
+
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ modifiedOption = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setDefault --
+//
+
+void option_register::setDefault(const char* aString) {
+ if (aString == NULL) {
+ std::cout << "Error: default string cannot be null" << std::endl;
+ exit(1);
+ }
+
+ if (defaultOption != NULL) {
+ delete [] defaultOption;
+ }
+ if (aString == NULL) {
+ defaultOption = NULL;
+ } else {
+ defaultOption = new char[strlen(aString) + 1];
+ strcpy(defaultOption, aString);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setDefinition --
+//
+
+void option_register::setDefinition(const char* aString) {
+
+ if (definition != NULL) {
+ delete [] definition;
+ }
+ if (aString == NULL) {
+ definition = NULL;
+ } else {
+ definition = new char[strlen(aString) + 1];
+ strcpy(definition, aString);
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setModified --
+//
+
+void option_register::setModified(const char* aString) {
+ if (modifiedOption != NULL) {
+ delete [] modifiedOption;
+ }
+ if (aString == NULL) {
+ modifiedOption = NULL;
+ } else {
+ modifiedOption = new char[strlen(aString) + 1];
+ strcpy(modifiedOption, aString);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// option_register::setType --
+//
+
+void option_register::setType(char aType) {
+ type = aType;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/// option_list class definitions ///////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////
+//
+// option_list::option_list --
+//
+
+option_list::option_list(void) {
+ name = NULL;
+ index = -1;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::option_list --
+//
+
+option_list::option_list(const char* optionName, int anIndex) {
+ name = NULL;
+ setIndex(anIndex);
+ setName(optionName);
+}
+
+
+
+//////////////////////////////
+//
+// option_list::~option_list --
+//
+
+option_list::~option_list() {
+ if (name != NULL) {
+ delete [] name;
+ }
+ name = NULL;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::getIndex --
+//
+
+int option_list::getIndex(void) {
+ return index;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::getName --
+//
+
+const char* option_list::getName(void) {
+ return name;
+}
+
+
+
+//////////////////////////////
+//
+// option_list::setName --
+//
+
+void option_list::setName(const char* aString) {
+ if (name != NULL) {
+ delete [] name;
+ }
+ name = new char[strlen(aString) + 1];
+ strcpy(name, aString);
+}
+
+
+
+//////////////////////////////
+//
+// option_list::setIndex --
+//
+
+void option_list::setIndex(int anIndex) {
+ index = anIndex;
+}
+
+
+
+// md5sum: be3cc8ad0380820a9ea96739dc989657 - Options_private.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_alsa.cpp b/src/midiio/src/Sequencer_alsa.cpp
new file mode 100644
index 0000000..4c80e22
--- /dev/null
+++ b/src/midiio/src/Sequencer_alsa.cpp
@@ -0,0 +1,643 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:10:02 PDT 2000
+// Last Modified: Sat Oct 13 14:51:43 PDT 2001 (updated for ALSA 0.9 interface)
+// Filename: ...sig/maint/code/control/Sequencer_alsa.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA raw midi devices. This class
+// is inherited by the classes MidiInPort_alsa and
+// MidiOutPort_alsa.
+//
+
+#if defined(LINUX) && defined(ALSA)
+
+#include "Collection.h"
+#include <alsa/asoundlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream>
+#include <stdio.h>
+#include <dirent.h> /* for reading filename for MIDI info */
+#include "Sequencer_alsa.h"
+
+typedef unsigned char uchar;
+
+// define static variables:
+int Sequencer_alsa::class_count = 0;
+int Sequencer_alsa::initialized = 0;
+
+// static variables for MIDI I/O information database
+int Sequencer_alsa::indevcount = 0;
+int Sequencer_alsa::outdevcount = 0;
+
+Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_in;
+Collection<snd_rawmidi_t*> Sequencer_alsa::rawmidi_out;
+Collection<int> Sequencer_alsa::midiincard;
+Collection<int> Sequencer_alsa::midioutcard;
+Collection<int> Sequencer_alsa::midiindevice;
+Collection<int> Sequencer_alsa::midioutdevice;
+Collection<char*> Sequencer_alsa::midiinname;
+Collection<char*> Sequencer_alsa::midioutname;
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa::Sequencer_alsa --
+// default value: autoOpen = 1;
+//
+
+Sequencer_alsa::Sequencer_alsa(int autoOpen) {
+ if (class_count < 0) {
+ std::cerr << "Unusual class instantiation count: " << class_count << std::endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ // will not autoOpen
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::~Sequencer_alsa --
+//
+
+Sequencer_alsa::~Sequencer_alsa() {
+
+ if (class_count == 1) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count <= 0) {
+ std::cerr << "Unusual class instantiation count: " << class_count << std::endl;
+ exit(1);
+ }
+
+ class_count--;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::close -- close the sequencer device. The device
+// automatically closes once the program ends.
+//
+
+void Sequencer_alsa::close(void) {
+ int i;
+
+ for (i=0; i<getNumInputs(); i++) {
+ if (rawmidi_in[i] != NULL) {
+ snd_rawmidi_close(rawmidi_in[i]);
+ rawmidi_in[i] = NULL;
+ }
+ }
+
+ for (i=0; i<getNumOutputs(); i++) {
+ if (rawmidi_out[i] != NULL) {
+ snd_rawmidi_close(rawmidi_out[i]);
+ rawmidi_out[i] = NULL;
+ }
+ }
+
+}
+
+
+void Sequencer_alsa::closeInput(int index) {
+ if (index < 0 || index >= rawmidi_in.getSize()) {
+ return;
+ }
+
+ if (rawmidi_in[index] != NULL) {
+ snd_rawmidi_close(rawmidi_in[index]);
+ rawmidi_in[index] = NULL;
+ }
+}
+
+
+void Sequencer_alsa::closeOutput(int index) {
+ if (index < 0 || index >= rawmidi_out.getSize()) {
+ return;
+ }
+
+ if (rawmidi_out[index] != NULL) {
+ snd_rawmidi_close(rawmidi_out[index]);
+ rawmidi_out[index] = NULL;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = std::cout, initial = "\t"
+//
+
+void Sequencer_alsa::displayInputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = std::cout, initial = "\t"
+//
+
+void Sequencer_alsa::displayOutputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midiinname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midioutname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_alsa::is_open(int mode, int index) {
+ if (mode == 0) {
+ // midi output
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+int Sequencer_alsa::is_open_in(int index) {
+ return is_open(1, index);
+}
+
+
+int Sequencer_alsa::is_open_out(int index) {
+ return is_open(0, index);
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_alsa::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_alsa::open(int direction, int index) {
+ if (direction == 0) {
+ return openOutput(index);
+ } else {
+ return openInput(index);
+ }
+}
+
+
+int Sequencer_alsa::openInput(int index) {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ }
+ int status;
+ char devname[128] = {0};
+ sprintf(devname, "hw:%d,%d", midiincard[index], midiindevice[index]);
+ status = snd_rawmidi_open(&rawmidi_in[index], NULL, devname, 0);
+ if (status == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+int Sequencer_alsa::openOutput(int index) {
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ }
+ int status;
+ char devname[128] = {0};
+ sprintf(devname, "hw:%d,%d", midioutcard[index], midioutdevice[index]);
+ status = snd_rawmidi_open(NULL, &rawmidi_out[index], devname, 0);
+ if (status == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_alsa::read(int dev, uchar* buf, int count) {
+ if (is_open_in(dev)) {
+ snd_rawmidi_read(rawmidi_in[dev], buf, count);
+ } else {
+ std::cout << "Warning: MIDI input " << dev << " is not open for reading"
+ << std::endl;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_alsa::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_alsa::write(int aDevice, int aByte) {
+ uchar byte[1];
+ byte[0] = (uchar)aByte;
+ return write(aDevice, byte, 1);
+}
+
+
+int Sequencer_alsa::write(int aDevice, uchar* bytes, int count) {
+ if (is_open_out(aDevice)) {
+ int status = snd_rawmidi_write(rawmidi_out[aDevice], bytes, count);
+ return status == count ? 1 : 0;
+ } else {
+ std::cout << "Warning: MIDI output " << aDevice << " is not open for writing"
+ << std::endl;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+int Sequencer_alsa::write(int aDevice, char* bytes, int count) {
+ return write(aDevice, (uchar*)bytes, count);
+}
+
+
+int Sequencer_alsa::write(int aDevice, int* bytes, int count) {
+ uchar *newBytes;
+ newBytes = new uchar[count];
+ for (int i=0; i<count; i++) {
+ newBytes[i] = (uchar)bytes[i];
+ }
+ int status = write(aDevice, newBytes, count);
+ delete [] newBytes;
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_alsa::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/snd/midiC%dD%d, and determines their names.
+//
+
+void Sequencer_alsa::buildInfoDatabase(void) {
+ if (initialized) {
+ return;
+ }
+
+ initialized = 1;
+
+ if (indevcount != 0 || outdevcount != 0) {
+ std::cout << "Error: Sequencer_alsa is already running" << std::endl;
+ std::cout << "Indevcout = " << indevcount << " and "
+ << " outdevcount = " << outdevcount << std::endl;
+ exit(1);
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+
+ midiincard.setSize(0);
+ midiincard.allowGrowth();
+ midioutcard.setSize(0);
+ midioutcard.allowGrowth();
+
+ midiindevice.setSize(0);
+ midiindevice.allowGrowth();
+ midioutdevice.setSize(0);
+ midioutdevice.allowGrowth();
+
+ midiinname.setSize(0);
+ midiinname.allowGrowth();
+ midioutname.setSize(0);
+ midioutname.allowGrowth();
+
+ rawmidi_in.setSize(256);
+ rawmidi_out.setSize(256);
+
+ // read number of MIDI inputs/output available
+ Collection<int> cards;
+ Collection<int> devices;
+ getPossibleMidiStreams(cards, devices);
+ char devname[128] = {0};
+
+ // check for MIDI input streams
+ int i;
+ for (i=0; i<cards.getSize(); i++) {
+ sprintf(devname, "hw:%d,%d", cards[i], devices[i]);
+ if (snd_rawmidi_open(&rawmidi_in[indevcount], NULL, devname, 0) == 0){
+ midiincard.append(cards[i]);
+ midiindevice.append(devices[i]);
+ snd_rawmidi_close(rawmidi_in[indevcount]);
+ rawmidi_in[indevcount] = NULL;
+ indevcount++;
+ }
+ }
+ for (i=0; i<rawmidi_in.getSize(); i++) {
+ rawmidi_in[i] = NULL;
+ }
+
+ // check for MIDI output streams
+ for (i=0; i<cards.getSize(); i++) {
+ sprintf(devname, "hw:%d,%d", cards[i], devices[i]);
+ if (snd_rawmidi_open(NULL, &rawmidi_out[outdevcount], devname, 0) == 0) {
+ midioutcard.append(cards[i]);
+ midioutdevice.append(devices[i]);
+ snd_rawmidi_close(rawmidi_out[outdevcount]);
+ rawmidi_out[indevcount] = NULL;
+ outdevcount++;
+ }
+ }
+ for (i=0; i<rawmidi_out.getSize(); i++) {
+ rawmidi_out[i] = NULL;
+ }
+
+ char buffer[256] = {0};
+ char* temp;
+ for (i=0; i<indevcount; i++) {
+ sprintf(buffer, "MIDI input %d: card %d, device %d", i,
+ midiincard[i], midiindevice[i]);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midiinname.append(temp);
+ }
+
+ for (i=0; i<outdevcount; i++) {
+ sprintf(buffer, "MIDI output %d: card %d, device %d", i,
+ midioutcard[i], midioutdevice[i]);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midioutname.append(temp);
+ }
+
+ midiincard.allowGrowth(0);
+ midioutcard.allowGrowth(0);
+ midiindevice.allowGrowth(0);
+ midioutdevice.allowGrowth(0);
+ midiinname.allowGrowth(0);
+ midioutname.allowGrowth(0);
+ rawmidi_in.allowGrowth(0);
+ rawmidi_out.allowGrowth(0);
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInDeviceValue --
+//
+
+int Sequencer_alsa::getInDeviceValue(int aDevice) const {
+ return midiindevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getInCardValue --
+//
+
+int Sequencer_alsa::getInCardValue(int aDevice) const {
+ return midiincard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutDeviceValue --
+//
+
+int Sequencer_alsa::getOutDeviceValue(int aDevice) const {
+ return midioutdevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::getOutCardValue --
+//
+
+int Sequencer_alsa::getOutCardValue(int aDevice) const {
+ return midioutcard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa::removeInfoDatabase --
+//
+
+void Sequencer_alsa::removeInfoDatabase(void) {
+ if (rawmidi_in.getSize() != 0) {
+ close();
+ }
+
+ if (rawmidi_out.getSize() != 0) {
+ close();
+ }
+
+ rawmidi_in.setSize(0);
+ rawmidi_out.setSize(0);
+ midiincard.setSize(0);
+ midioutcard.setSize(0);
+ midiindevice.setSize(0);
+ midioutdevice.setSize(0);
+
+ int i;
+ for (i=0; i<midiinname.getSize(); i++) {
+ if (midiinname[i] != NULL) {
+ delete [] midiinname[i];
+ }
+ }
+
+ for (i=0; i<midioutname.getSize(); i++) {
+ if (midioutname[i] != NULL) {
+ delete [] midioutname[i];
+ }
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+ initialized = 0;
+}
+
+
+
+//////////////////////////////
+//
+// getPossibleMidiStreams -- read the directory /dev/snd for files
+// that match the pattern midiC%dD%d, and extract the card/device
+// numbers from these filenames.
+//
+
+void Sequencer_alsa::getPossibleMidiStreams(Collection<int>& cards,
+ Collection<int>& devices) {
+
+ cards.setSize(0);
+ devices.setSize(0);
+ cards.allowGrowth(1);
+ devices.allowGrowth(1);
+
+ DIR* dir = opendir("/dev/snd");
+ if (dir == NULL) {
+// std::cout << "Error determining ALSA MIDI info: no directory called /dev/snd"
+// << std::endl;
+// exit(1);
+ }
+
+ // read each file in the directory and store information if it is a MIDI dev
+ else {
+ int card;
+ int device;
+ struct dirent *dinfo;
+ dinfo = readdir(dir);
+ int count;
+ while (dinfo != NULL) {
+ if (strncmp(dinfo->d_name, "midi", 4) == 0) {
+ count = sscanf(dinfo->d_name, "midiC%dD%d", &card, &device);
+ if (count == 2) {
+ cards.append(card);
+ devices.append(device);
+ }
+ }
+ dinfo = readdir(dir);
+ }
+
+ closedir(dir);
+ cards.allowGrowth(0);
+ devices.allowGrowth(0);
+ }
+}
+
+
+#endif /* LINUX and ALSA */
+
+// md5sum: 8ccf0e750be06aeea90cdc8a7cc4499c - Sequencer_alsa.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_alsa05.cpp b/src/midiio/src/Sequencer_alsa05.cpp
new file mode 100644
index 0000000..ad4ef2d
--- /dev/null
+++ b/src/midiio/src/Sequencer_alsa05.cpp
@@ -0,0 +1,518 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Thu May 11 21:10:02 PDT 2000
+// Last Modified: Wed Oct 3 22:18:27 PDT 2001 (frozen to ALSA 0.5)
+// Filename: ...sig/maint/code/control/Sequencer_alsa05.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_alsa05.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux ALSA raw midi devices. This class
+// is inherited by the classes MidiInPort_alsa05 and
+// MidiOutPort_alsa05.
+//
+
+#if defined(LINUX) && defined(ALSA05)
+
+#include "Collection.h"
+#include <sys/asoundlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream.h>
+#include <stdio.h>
+#include "Sequencer_alsa05.h"
+
+typedef unsigned char uchar;
+
+// define static variables:
+int Sequencer_alsa05::class_count = 0;
+int Sequencer_alsa05::initialized = 0;
+
+// static variables for MIDI I/O information database
+int Sequencer_alsa05::indevcount = 0;
+int Sequencer_alsa05::outdevcount = 0;
+
+Collection<snd_rawmidi_t*> Sequencer_alsa05::rawmidi_in;
+Collection<snd_rawmidi_t*> Sequencer_alsa05::rawmidi_out;
+Collection<int> Sequencer_alsa05::midiincard;
+Collection<int> Sequencer_alsa05::midioutcard;
+Collection<int> Sequencer_alsa05::midiindevice;
+Collection<int> Sequencer_alsa05::midioutdevice;
+Collection<char*> Sequencer_alsa05::midiinname;
+Collection<char*> Sequencer_alsa05::midioutname;
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa05::Sequencer_alsa05 --
+// default value: autoOpen = 1;
+//
+
+Sequencer_alsa05::Sequencer_alsa05(int autoOpen) {
+ if (class_count < 0) {
+ cerr << "Unusual class instatiation count: " << class_count << endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ if (autoOpen) {
+ open();
+ }
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::~Sequencer_alsa05 --
+//
+
+Sequencer_alsa05::~Sequencer_alsa05() {
+
+ if (class_count == 1) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count <= 0) {
+ cerr << "Unusual class instatiation count: " << class_count << endl;
+ exit(1);
+ }
+
+ class_count--;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::close -- close the sequencer device. The device
+// automatically closes once the program ends.
+//
+
+void Sequencer_alsa05::close(void) {
+ int i;
+
+ for (i=0; i<getNumInputs(); i++) {
+ if (rawmidi_in[i] != NULL) {
+ snd_rawmidi_close(rawmidi_in[i]);
+ rawmidi_in[i] = NULL;
+ }
+ }
+
+ for (i=0; i<getNumOutputs(); i++) {
+ if (rawmidi_out[i] != NULL) {
+ snd_rawmidi_close(rawmidi_out[i]);
+ rawmidi_out[i] = NULL;
+ }
+ }
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_alsa05::displayInputs(ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_alsa05::displayOutputs(ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa05::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midiinname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa05::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_alsa05::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_alsa05::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return midioutname[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_alsa05::is_open(int mode, int index) {
+ if (mode == 0) {
+ // midi output
+ if (rawmidi_out[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (rawmidi_in[index] != NULL) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+int Sequencer_alsa05::is_open_in(int index) {
+ return is_open(1, index);
+}
+
+
+int Sequencer_alsa05::is_open_out(int index) {
+ return is_open(0, index);
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_alsa05::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_alsa05::open(void) {
+ if (rawmidi_out.getSize() != 0 || rawmidi_in.getSize() != 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_alsa05::read(int dev, uchar* buf, int count) {
+ snd_rawmidi_read(rawmidi_in[dev], buf, count);
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_alsa05::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_alsa05::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_alsa05::write(int aDevice, int aByte) {
+ uchar byte[1];
+ byte[0] = (uchar)aByte;
+ return write(aDevice, byte, 1);
+}
+
+
+int Sequencer_alsa05::write(int aDevice, uchar* bytes, int count) {
+ int status = snd_rawmidi_write(rawmidi_out[aDevice], bytes, count);
+ return status == count ? 1 : 0;
+}
+
+
+int Sequencer_alsa05::write(int aDevice, char* bytes, int count) {
+ return write(aDevice, (uchar*)bytes, count);
+}
+
+
+int Sequencer_alsa05::write(int aDevice, int* bytes, int count) {
+ uchar *newBytes;
+ newBytes = new uchar[count];
+ for (int i=0; i<count; i++) {
+ newBytes[i] = (uchar)bytes[i];
+ }
+ int status = write(aDevice, newBytes, count);
+ delete [] newBytes;
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_alsa05::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/snd/midiXX, and determines their names.
+//
+
+void Sequencer_alsa05::buildInfoDatabase(void) {
+ if (initialized) {
+ return;
+ }
+
+ initialized = 1;
+
+ if (indevcount != 0 || outdevcount != 0) {
+ cout << "Error: Sequencer_alsa05 is already running" << endl;
+ cout << "Indevcout = " << indevcount << " and "
+ << " outdevcount = " << outdevcount << endl;
+ exit(1);
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+
+ midiincard.setSize(0);
+ midiincard.allowGrowth();
+ midioutcard.setSize(0);
+ midioutcard.allowGrowth();
+
+ midiindevice.setSize(0);
+ midiindevice.allowGrowth();
+ midioutdevice.setSize(0);
+ midioutdevice.allowGrowth();
+
+ midiinname.setSize(0);
+ midiinname.allowGrowth();
+ midioutname.setSize(0);
+ midioutname.allowGrowth();
+
+ rawmidi_in.setSize(256);
+ rawmidi_out.setSize(256);
+
+ // read number of MIDI inputs/output available
+ int card;
+ int device;
+
+ for (card=0; card<16; card++) {
+ for (device=0; device<16; device++) {
+ if (snd_rawmidi_open(&rawmidi_in[indevcount], card, device,
+ O_RDONLY | O_APPEND | O_NONBLOCK) == 0){
+ midiincard.append(card);
+ midiindevice.append(device);
+ indevcount++;
+ }
+ }
+ }
+ rawmidi_in.setSize(indevcount);
+
+ for (card=0; card<16; card++) {
+ for (device=0; device<16; device++) {
+ if (snd_rawmidi_open(&rawmidi_out[outdevcount], card,
+ device, O_WRONLY | O_APPEND | O_NONBLOCK) == 0) {
+ midioutcard.append(card);
+ midioutdevice.append(device);
+ outdevcount++;
+ }
+ }
+ }
+ rawmidi_out.setSize(indevcount);
+
+ int i;
+ char buffer[256] = {0};
+ char* temp;
+ for (i=0; i<indevcount; i++) {
+ sprintf(buffer, "MIDI input %d", i);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midiinname.append(temp);
+ }
+
+ for (i=0; i<outdevcount; i++) {
+ sprintf(buffer, "MIDI output %d", i);
+ temp = new char[strlen(buffer) + 1];
+ strcpy(temp, buffer);
+ midioutname.append(temp);
+ }
+
+ midiincard.allowGrowth(0);
+ midioutcard.allowGrowth(0);
+ midiindevice.allowGrowth(0);
+ midioutdevice.allowGrowth(0);
+ midiinname.allowGrowth(0);
+ midioutname.allowGrowth(0);
+ rawmidi_in.allowGrowth(0);
+ rawmidi_out.allowGrowth(0);
+
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInDeviceValue --
+//
+
+int Sequencer_alsa05::getInDeviceValue(int aDevice) const {
+ return midiindevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getInCardValue --
+//
+
+int Sequencer_alsa05::getInCardValue(int aDevice) const {
+ return midiincard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutDeviceValue --
+//
+
+int Sequencer_alsa05::getOutDeviceValue(int aDevice) const {
+ return midioutdevice[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::getOutCardValue --
+//
+
+int Sequencer_alsa05::getOutCardValue(int aDevice) const {
+ return midioutcard[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_alsa05::removeInfoDatabase --
+//
+
+void Sequencer_alsa05::removeInfoDatabase(void) {
+ if (rawmidi_in.getSize() != 0) {
+ close();
+ }
+
+ if (rawmidi_out.getSize() != 0) {
+ close();
+ }
+
+ rawmidi_in.setSize(0);
+ rawmidi_out.setSize(0);
+ midiincard.setSize(0);
+ midioutcard.setSize(0);
+ midiindevice.setSize(0);
+ midioutdevice.setSize(0);
+
+ int i;
+ for (i=0; i<midiinname.getSize(); i++) {
+ if (midiinname[i] != NULL) {
+ delete [] midiinname[i];
+ }
+ }
+
+ for (i=0; i<midioutname.getSize(); i++) {
+ if (midioutname[i] != NULL) {
+ delete [] midioutname[i];
+ }
+ }
+
+ indevcount = 0;
+ outdevcount = 0;
+ initialized = 0;
+}
+
+
+#endif /* LINUX and ALSA05 */
+
+
+// md5sum: b47021f0b71b2bc1555755584777c9a8 - Sequencer_alsa05.cpp =css= 20030102
diff --git a/src/midiio/src/Sequencer_oss.cpp b/src/midiio/src/Sequencer_oss.cpp
new file mode 100644
index 0000000..db9258e
--- /dev/null
+++ b/src/midiio/src/Sequencer_oss.cpp
@@ -0,0 +1,809 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Jan 3 21:02:02 PST 1999
+// Last Modified: Fri Jan 8 04:50:05 PST 1999
+// Last Modified: Wed May 10 17:00:11 PDT 2000 (name change from _linux to _oss)
+// Filename: ...sig/maint/code/control/MidiOutPort/Sequencer_oss.cpp
+// Web Address: http://sig.sapp.org/src/sig/Sequencer_oss.cpp
+// Syntax: C++
+//
+// Description: Basic MIDI input/output functionality for the
+// Linux OSS midi device /dev/sequencer. This class
+// is inherited by the classes MidiInPort_oss and
+// MidiOutPort_oss.
+//
+
+#ifdef LINUX
+
+#include <stdlib.h>
+
+
+#include <linux/soundcard.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <iostream>
+#include "Sequencer_oss.h"
+
+
+// define static variables:
+const char* Sequencer_oss::sequencer = "/dev/sequencer";
+int Sequencer_oss::sequencer_fd = -1;
+int Sequencer_oss::class_count = 0;
+int Sequencer_oss::initialized = 0;
+uchar Sequencer_oss::midi_write_packet[4] = {SEQ_MIDIPUTC, 0, 0, 0};
+uchar Sequencer_oss::midi_read_packet[4];
+
+
+// static variables for MIDI I/O information database
+int Sequencer_oss::indevcount = 0;
+int Sequencer_oss::outdevcount = 0;
+
+int* Sequencer_oss::indevnum = NULL;
+int* Sequencer_oss::outdevnum = NULL;
+
+int* Sequencer_oss::indevtype = NULL;
+int* Sequencer_oss::outdevtype = NULL;
+
+char** Sequencer_oss::indevnames = NULL;
+char** Sequencer_oss::outdevnames = NULL;
+
+
+
+///////////////////////////////
+//
+// Sequencer_oss::Sequencer_oss --
+// default value: autoOpen = 1;
+//
+
+Sequencer_oss::Sequencer_oss(int autoOpen) {
+ if (autoOpen) {
+ open();
+ }
+
+ if (class_count < 0) {
+ std::cerr << "Unusual class instatiation count: " << class_count << std::endl;
+ exit(1);
+ } else if (class_count == 0) {
+ buildInfoDatabase();
+ }
+
+ class_count++;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::~Sequencer_oss --
+//
+
+Sequencer_oss::~Sequencer_oss() {
+ class_count--;
+
+ if (class_count == 0) {
+ close();
+ removeInfoDatabase();
+ } else if (class_count < 0) {
+ std::cerr << "Unusual class instatiation count: " << class_count << std::endl;
+ exit(1);
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::close -- close the sequencer device. The device
+// automatically closes once the program ends, but you can close it
+// so that other programs can use it.
+//
+
+void Sequencer_oss::close(void) {
+ ::close(getFd());
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::displayInputs -- display a list of the
+// available MIDI input devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_oss::displayInputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumInputs(); i++) {
+ out << initial << i << ": " << getInputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::displayOutputs -- display a list of the
+// available MIDI output devices.
+// default values: out = cout, initial = "\t"
+//
+
+void Sequencer_oss::displayOutputs(std::ostream& out, char* initial) {
+ for (int i=0; i<getNumOutputs(); i++) {
+ out << initial << i << ": " << getOutputName(i) << '\n';
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInputName -- returns a string to the name of
+// the specified input device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_oss::getInputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevnames[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getNumInputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_oss::getNumInputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return indevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getNumOutputs -- returns the total number of
+// MIDI inputs that can be used.
+//
+
+int Sequencer_oss::getNumOutputs(void) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ return outdevcount;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutputName -- returns a string to the name of
+// the specified output device. The string will remain valid as
+// long as there are any sequencer devices in existence.
+//
+
+const char* Sequencer_oss::getOutputName(int aDevice) {
+ if (initialized == 0) {
+ buildInfoDatabase();
+ }
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevnames[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::is_open -- returns true if the
+// sequencer device is open, false otherwise.
+//
+
+int Sequencer_oss::is_open(void) {
+ if (getFd() > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+/////////////////////////////
+//
+// Sequencer_oss::open -- returns true if the device
+// was successfully opended (or already opened)
+//
+
+int Sequencer_oss::open(void) {
+ if (getFd() <= 0) {
+ setFd(::open(sequencer, O_RDWR, 0));
+ }
+
+ return is_open();
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::read -- reads MIDI bytes and also stores the
+// device from which the byte was read from. Timing is not
+// saved from the device. If needed, then it would have to
+// be saved in this function, or just return the raw packet
+// data (use rawread function).
+//
+
+void Sequencer_oss::read(uchar* buf, uchar* dev, int count) {
+ int i = 0;
+ while (i < count) {
+ ::read(getFd(), midi_read_packet, sizeof(midi_read_packet));
+ if (midi_read_packet[1] == SEQ_MIDIPUTC) {
+ buf[i] = midi_read_packet[1];
+ dev[i] = midi_read_packet[2];
+ i++;
+ }
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::rawread -- read Input MIDI packets.
+// each packet contains 4 bytes.
+//
+
+void Sequencer_oss::rawread(uchar* buf, int packetCount) {
+ ::read(getFd(), buf, packetCount * 4);
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::rebuildInfoDatabase -- rebuild the internal
+// database that keeps track of the MIDI input and output devices.
+//
+
+void Sequencer_oss::rebuildInfoDatabase(void) {
+ removeInfoDatabase();
+ buildInfoDatabase();
+}
+
+
+
+///////////////////////////////
+//
+// Sequencer_oss::write -- Send a byte out the specified MIDI
+// port which can be either an internal or an external synthesizer.
+//
+
+int Sequencer_oss::write(int device, int aByte) {
+ int status = 0;
+
+ switch (getOutputType(device)) {
+ case MIDI_EXTERNAL:
+ midi_write_packet[1] = (uchar) (0xff & aByte);
+ midi_write_packet[2] = getOutDeviceValue(device);
+ status = ::write(getFd(), midi_write_packet,sizeof(midi_write_packet));
+ break;
+ case MIDI_INTERNAL:
+ status = writeInternal(getOutDeviceValue(device), aByte);
+ break;
+ }
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+int Sequencer_oss::write(int device, uchar* bytes, int count) {
+ int status = 1;
+ for (int i=0; i<count; i++) {
+ status &= write(device, bytes[i]);
+ }
+ return status;
+}
+
+
+int Sequencer_oss::write(int device, char* bytes, int count) {
+ return write(device, (uchar*)bytes, count);
+}
+
+
+int Sequencer_oss::write(int device, int* bytes, int count) {
+ int status = 1;
+ for (int i=0; i<count; i++) {
+ status &= write(device, bytes[i]);
+ }
+ return status;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions
+//
+
+//////////////////////////////
+//
+// Sequencer_oss::buildInfoDatabase -- determines the number
+// of MIDI input and output devices available from
+// /dev/sequencer, and determines their names.
+//
+
+void Sequencer_oss::buildInfoDatabase(void) {
+ int status;
+ initialized = 1;
+
+ int startup = sequencer_fd == -1 ? 0 : 1;
+ if (startup == 0) {
+ // setup the file descriptor for /dev/sequencer
+ sequencer_fd = ::open(sequencer, O_RDWR);
+ if (sequencer_fd < 0) {
+// std::cout << "Error: cannot open " << sequencer << std::endl;
+// exit(1);
+ }
+ else {
+ // read number of inputs available (external MIDI devices only)
+ status = ioctl(getFd(), SNDCTL_SEQ_NRMIDIS, &indevcount);
+ if (status!= 0) {
+ std::cerr << "Error determining the number of MIDI inputs" << std::endl;
+ exit(1);
+ }
+
+ // read number of output available
+ int extmidi = indevcount;
+ int intmidi;
+ status = ioctl(getFd(), SNDCTL_SEQ_NRSYNTHS, &intmidi);
+ if (status!= 0) {
+ std::cerr << "Error determining the number of MIDI inputs" << std::endl;
+ exit(1);
+ }
+ outdevcount = extmidi + intmidi;
+
+ // allocate space for names and device number arrays
+ if (indevnum != NULL || outdevnum != NULL || indevnames != NULL ||
+ outdevnames != NULL || indevtype != NULL || outdevtype != NULL) {
+ std::cerr << "Error: buildInfoDatabase called twice." << std::endl;
+ exit(1);
+ }
+
+ indevnum = new int[indevcount];
+ outdevnum = new int[outdevcount];
+
+ indevtype = new int[indevcount];
+ outdevtype = new int[outdevcount];
+
+ indevnames = new char*[indevcount];
+ outdevnames = new char*[outdevcount];
+
+
+ // fill in the device translation table and fill in the device names
+ int i;
+ struct midi_info midiinfo;
+ for (i=0; i<indevcount; i++) {
+ midiinfo.device = i;
+ status = ioctl(getFd(), SNDCTL_MIDI_INFO, &midiinfo);
+ if (status != 0) {
+ std::cerr << "Error while reading MIDI device " << i << std::endl;
+ exit(1);
+ }
+
+ indevnum[i] = midiinfo.device;
+ outdevnum[i] = midiinfo.device;
+ indevtype[i] = MIDI_EXTERNAL;
+ outdevtype[i] = MIDI_EXTERNAL;
+ indevnames[i] = new char[strlen(midiinfo.name) + 1 + 10];
+ outdevnames[i] = new char[strlen(midiinfo.name) + 1 + 11];
+ strcpy(indevnames[i], midiinfo.name);
+ strcpy(outdevnames[i], midiinfo.name);
+ strcat(indevnames[i], " (MIDI In)");
+ strcat(outdevnames[i], " (MIDI Out)");
+ }
+
+ char tempstring[1024] = {0};
+ struct synth_info synthinfo;
+ for (i=0; i<intmidi; i++) {
+ synthinfo.device = i;
+ status = ioctl(getFd(), SNDCTL_SYNTH_INFO, &synthinfo);
+ if (status != 0) {
+ std::cerr << "Error while reading MIDI device " << i << std::endl;
+ exit(1);
+ }
+ outdevnum[extmidi+i] = i;
+ outdevtype[extmidi + i] = MIDI_INTERNAL;
+
+ strcpy(tempstring, synthinfo.name);
+ switch (synthinfo.synth_type) {
+ case SYNTH_TYPE_FM: // 0
+ strcat(tempstring, " (FM");
+ switch (synthinfo.synth_subtype) {
+ case FM_TYPE_ADLIB: // 0
+ strcat(tempstring, " Adlib");
+ break;
+ case FM_TYPE_OPL3: // 1
+ strcat(tempstring, " OPL3");
+ break;
+ }
+ strcat(tempstring, ")");
+ break;
+ case SYNTH_TYPE_SAMPLE: // 1
+ strcat(tempstring, " (Wavetable)");
+ break;
+ case SYNTH_TYPE_MIDI: // 2
+ strcat(tempstring, " (MIDI Interface");
+ switch (synthinfo.synth_subtype) {
+ case SYNTH_TYPE_MIDI: // 0x401
+ strcat(tempstring, " MPU401");
+ break;
+ }
+ strcat(tempstring, ")");
+ break;
+ }
+ outdevnames[i+extmidi] = new char[strlen(tempstring) + 1];
+ strcpy(outdevnames[i+extmidi], tempstring);
+ }
+
+
+ if (startup == 0) {
+ ::close(sequencer_fd);
+ }
+ }
+ }
+}
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getFd -- returns the file descriptor of the
+// sequencer device.
+//
+
+int Sequencer_oss::getFd(void) {
+ return sequencer_fd;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInDeviceValue --
+//
+
+int Sequencer_oss::getInDeviceValue(int aDevice) const {
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevnum[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getInputType -- returns 1 = external MIDI,
+// 2 = internal MIDI
+//
+
+int Sequencer_oss::getInputType(int aDevice) const {
+ if (aDevice >= getNumInputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max in ("
+ << getNumInputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return indevtype[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutDeviceValue --
+//
+
+int Sequencer_oss::getOutDeviceValue(int aDevice) const {
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevnum[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::getOutputType -- returns 1 = external MIDI,
+// 2 = internal MIDI
+//
+
+int Sequencer_oss::getOutputType(int aDevice) const {
+ if (aDevice >= getNumOutputs()) {
+ std::cerr << "Error: " << aDevice << " is greater than max out ("
+ << getNumOutputs() << ")" << std::endl;
+ exit(1);
+ }
+
+ return outdevtype[aDevice];
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::removeInfoDatabase --
+//
+
+void Sequencer_oss::removeInfoDatabase(void) {
+ initialized = 0;
+
+ if (indevnum != NULL) delete [] indevnum;
+ if (outdevnum != NULL) delete [] outdevnum;
+ if (indevtype != NULL) delete [] indevtype;
+ if (outdevtype != NULL) delete [] outdevtype;
+
+ int i;
+ if (indevnames != NULL) {
+ for (i=0; i<indevcount; i++) {
+ if (indevnames[i] != NULL) delete [] indevnames[i];
+ }
+ delete [] indevnames;
+ }
+
+ if (outdevnames != NULL) {
+ for (i=0; i<outdevcount; i++) {
+ if (outdevnames[i] != NULL) delete [] outdevnames[i];
+ }
+ delete [] outdevnames;
+ }
+
+ indevnum = NULL;
+ outdevnum = NULL;
+ indevtype = NULL;
+ outdevtype = NULL;
+ indevnames = NULL;
+ outdevnames = NULL;
+
+ indevcount = 0;
+ outdevcount = 0;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::setFd --
+//
+
+void Sequencer_oss::setFd(int anFd) {
+ sequencer_fd = anFd;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// private functions dealing with the stupid internal sythesizer messages
+// which have to be processed as complete messages as opposed to
+// external MIDI devices which are processed on the driver level as
+// discrete bytes.
+//
+
+// static variables related to the processing of message for internal MIDI:
+uchar Sequencer_oss::synth_write_message[8];
+uchar Sequencer_oss::synth_message_buffer[1024] = {0};
+int Sequencer_oss::synth_message_buffer_count = 0;
+int Sequencer_oss::synth_message_bytes_expected = 0;
+int Sequencer_oss::synth_message_curr_device = -1;
+
+
+//////////////////////////////
+//
+// Sequencer_oss::writeInternal -- the device number is the
+// driver's device number *NOT* this class's device numbering
+// system. MIDI bytes are stored in a buffer until a complete
+// message is received, then a synth message is generated.
+// While a complete message is being received, the device number
+// cannot change. The first byte of a message must be a MIDI
+// command (i.e., no running status).
+//
+
+int Sequencer_oss::writeInternal(int aDevice, int aByte) {
+ int status = 0;
+
+ if (synth_message_bytes_expected == 0) {
+ // a new message is coming in.
+ synth_message_curr_device = aDevice;
+ if (aByte < 128) {
+ std::cerr << "Error: MIDI output byte: " << aByte
+ << " is not a command byte." << std::endl;
+ exit(1);
+ } else {
+ synth_message_buffer[0] = aByte;
+ synth_message_buffer_count = 1;
+ }
+
+ switch (aByte & 0xf0) {
+ case 0x80: synth_message_bytes_expected = 3; break;
+ case 0x90: synth_message_bytes_expected = 3; break;
+ case 0xA0: synth_message_bytes_expected = 3; break;
+ case 0xB0: synth_message_bytes_expected = 3; break;
+ case 0xC0: synth_message_bytes_expected = 2; break;
+ case 0xD0: synth_message_bytes_expected = 2; break;
+ case 0xE0: synth_message_bytes_expected = 3; break;
+ case 0xF0: std::cerr << "Can't handle 0xE0 yet" << std::endl; exit(1);
+ default: std::cerr << "Unknown error" << std::endl; exit(1);
+ }
+ }
+
+ // otherwise expecting at least one more byte for the MIDI message
+ else {
+ if (synth_message_curr_device != aDevice) {
+ std::cerr << "Error: device number changed during message" << std::endl;
+ exit(1);
+ }
+ if (aByte > 127) {
+ std::cerr << "Error: expecting MIDI data but got MIDI command: "
+ << aByte << std::endl;
+ exit(1);
+ }
+
+ synth_message_buffer[synth_message_buffer_count++] = aByte;
+ }
+
+ // check to see if the message is complete:
+ if (synth_message_bytes_expected == synth_message_buffer_count) {
+ status = transmitMessageToInternalSynth();
+ synth_message_bytes_expected = 0;
+ synth_message_buffer_count = 0;
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitMessageToInternalSynth -- send the stored
+// MIDI message to the internal synthesizer.
+//
+
+int Sequencer_oss::transmitMessageToInternalSynth(void) {
+ int status;
+ switch (synth_message_buffer[0] & 0xf0) {
+ case 0x80: // Note-off
+ case 0x90: // Note-on
+ case 0xA0: // Aftertouch
+ status = transmitVoiceMessage();
+ break;
+ case 0xB0: // Control change
+ case 0xC0: // Patch change
+ case 0xD0: // Channel pressure
+ case 0xE0: // Pitch wheel
+ status = transmitCommonMessage();
+ break;
+ case 0xF0:
+ std::cerr << "Cannot handle 0xf0 commands yet" << std::endl;
+ exit(1);
+ break;
+ default:
+ std::cerr << "Error: unknown MIDI command" << std::endl;
+ exit(1);
+ }
+
+ return status;
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitVoiceMessage -- send a voice-type MIDI
+// message to an internal synthesizer.
+//
+
+int Sequencer_oss::transmitVoiceMessage(void) {
+ synth_write_message[0] = EV_CHN_VOICE;
+ synth_write_message[1] = synth_message_curr_device;
+ synth_write_message[2] = synth_message_buffer[0] & 0xf0;
+ synth_write_message[3] = synth_message_buffer[0] & 0x0f;
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = synth_message_buffer[2];
+ synth_write_message[6] = 0;
+ synth_write_message[7] = 0;
+
+ int status;
+ status = ::write(getFd(), synth_write_message, sizeof(synth_write_message));
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Sequencer_oss::transmitCommonMessage -- send a common-type MIDI
+// message to an internal synthesizer.
+//
+
+int Sequencer_oss::transmitCommonMessage(void) {
+ synth_write_message[0] = EV_CHN_COMMON;
+ synth_write_message[1] = synth_message_curr_device;
+ synth_write_message[2] = synth_message_buffer[0] & 0xf0;
+ synth_write_message[3] = synth_message_buffer[0] & 0x0f;
+
+ switch (synth_write_message[2]) {
+ case 0xB0: // Control change
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = 0;
+ synth_write_message[6] = synth_message_buffer[2];
+ synth_write_message[7] = 0;
+ break;
+ case 0xC0: // Patch change
+ case 0xD0: // Channel pressure
+ synth_write_message[4] = synth_message_buffer[1];
+ synth_write_message[5] = 0;
+ synth_write_message[6] = 0;
+ synth_write_message[7] = 0;
+ break;
+ case 0xE0: // Pitch wheel
+ synth_write_message[4] = 0;
+ synth_write_message[5] = 0;
+ synth_write_message[6] = synth_message_buffer[1];
+ synth_write_message[7] = synth_message_buffer[2];
+ break;
+ default:
+ std::cerr << "Unknown Common MIDI message" << std::endl;
+ exit(1);
+ }
+
+ int status;
+ status = ::write(getFd(), synth_write_message, sizeof(synth_write_message));
+
+ if (status > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+
+#endif // LINUX
+// md5sum: bc7b96041137b22f3d3c35376b5912c6 - Sequencer_oss.cpp =css= 20030102
diff --git a/src/midiio/src/SigTimer.cpp b/src/midiio/src/SigTimer.cpp
new file mode 100644
index 0000000..5786098
--- /dev/null
+++ b/src/midiio/src/SigTimer.cpp
@@ -0,0 +1,498 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Thanks to: Erik Neuenschwander <erikn@leland.stanford.edu>
+// for Windows 95 assembly code for Pentium clock cycles.
+// Ozgur Izmirli <ozgur@ccrma.stanford.edu>
+// for concept of periodic timer.
+// Creation Date: Mon Oct 13 11:34:57 GMT-0800 1997
+// Last Modified: Tue Feb 10 21:05:19 GMT-0800 1998
+// Last Modified: Sat Sep 19 15:56:48 PDT 1998
+// Last Modified: Mon Feb 22 04:44:25 PST 1999
+// Last Modified: Sun Nov 28 12:39:39 PST 1999 (added adjustPeriod())
+// Filename: .../sig/code/control/SigTimer/SigTimer.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/SigTimer.cpp
+// Syntax: C++
+//
+// Description: This class can only be used on Motorola Pentinum 75 Mhz
+// chips or better because the timing information is
+// extracted from the clock cycle count from a register
+// on the CPU itself. This class will estimate the
+// speed of the computer, but it would be better if there
+// was a way of finding out the speed from some function.
+// This class is used primarily for timing of MIDI input
+// and output at a millisecond resolution.
+//
+
+
+#include "SigTimer.h"
+#include <iostream>
+#include <stdlib.h>
+
+
+// get Sleep or usleep function definition for measureCpu function:
+#ifdef VISUAL
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #undef WIN32_LEAN_AND_MEAN
+#else
+ #include <unistd.h>
+#endif
+
+
+// declare static variables
+int64bits SigTimer::globalOffset = 0;
+int SigTimer::cpuSpeed = 0; // in cycles per second
+
+
+
+//////////////////////////////
+//
+// SigTimer::SigTimer
+//
+
+SigTimer::SigTimer(void) {
+ if (globalOffset == 0) { // coordinate offset between timers
+ globalOffset = clockCycles();
+ }
+ if (cpuSpeed <= 0) { // initialize CPU speed value
+ cpuSpeed = measureCpuSpeed(1);
+ if (cpuSpeed <= 0) {
+ cpuSpeed = 100000000;
+ }
+ }
+
+ offset = globalOffset; // initialize the start time of timer
+ ticksPerSecond = 1000; // default of 1000 ticks per second
+ period = 1000.0; // default period of once per second
+}
+
+
+SigTimer::SigTimer(int aSpeed) {
+ if (globalOffset == 0) {
+ globalOffset = clockCycles();
+ }
+ cpuSpeed = aSpeed;
+
+ offset = globalOffset;
+ ticksPerSecond = 1000;
+ period = 1000.0; // default period of once per second
+}
+
+
+SigTimer::SigTimer(SigTimer& aTimer) {
+ offset = aTimer.offset;
+ ticksPerSecond = aTimer.ticksPerSecond;
+ period = aTimer.period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::~SigTimer
+//
+
+SigTimer::~SigTimer() {
+ // do nothing
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::adjustPeriod -- adjust the period of the timer.
+//
+
+void SigTimer::adjustPeriod(double periodDelta) {
+ offset -= (int64bits)(getCpuSpeed() * getPeriod() * periodDelta /
+ getTicksPerSecond());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::clockCycles -- returns the number of clock cycles since last reboot
+// HARDWARE DEPENDENT -- currently for Pentiums only.
+// static function.
+//
+
+
+int64bits SigTimer::clockCycles() {
+#ifndef VISUAL
+ int64bits output;
+
+ // For Pentiums, you can get the number of clock cycles elapsed
+ // since the last reboot with the following assembler code:
+ __asm__ volatile (".byte 0x0f, 0x31" : "=A" (output));
+
+#else
+ int64bits output;
+ unsigned long high_end, low_end;
+ __asm {
+ __asm _emit 0x0f __asm _emit 0x31
+ mov high_end, edx
+ mov low_end, eax
+ }
+ output = high_end;
+ output = output << 32;
+ output += low_end;
+#endif
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::expired -- returns the integral number of periods
+// That have passed since the last update or reset.
+// See getPeriodCount which returns a floating point
+// count of the period position.
+//
+
+
+int SigTimer::expired(void) const {
+ return (int)(getTime()/period);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getCpuSpeed -- returns the CPU speed of the computer.
+// (static function)
+//
+
+int SigTimer::getCpuSpeed(void) {
+ return cpuSpeed;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getPeriod -- returns the timing period of the timer,
+// if the timer is being used as a periodic timer.
+//
+
+double SigTimer::getPeriod(void) const {
+ return period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getPeriodCount -- returns the current period count
+// of the timer as a double. Similar in behavior to expired
+// function but lists the current fraction of a period.
+//
+
+double SigTimer::getPeriodCount(void) const {
+ return (double)getTime()/period;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTempo -- returns the current tempo in terms
+// of beats (ticks) per minute.
+//
+
+double SigTimer::getTempo(void) const {
+ return getTicksPerSecond() * 60.0 / getPeriod();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTicksPerSecond -- return the number of ticks per
+// second.
+//
+
+int SigTimer::getTicksPerSecond(void) const {
+ return ticksPerSecond;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTime -- returns time in milliseconds by default.
+// time can be altered to be in some other unit of time
+// by using the setTicksPerSecond function.
+// (Default is 1000 ticks per second.)
+//
+
+int SigTimer::getTime(void) const {
+ return (int)((clockCycles()-offset)/getFactor());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTimeInSeconds
+//
+
+double SigTimer::getTimeInSeconds(void) const {
+ return ((clockCycles()-offset)/(double)cpuSpeed);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::getTimeInTicks
+//
+
+int SigTimer::getTimeInTicks(void) const {
+ return (int)((clockCycles()-offset)/getFactor());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::measureCpuSpeed -- returns the number of clock cycles in
+// one second. Accuracy to about +/- 5%.
+// default value: quantize = 0.
+//
+
+int SigTimer::measureCpuSpeed(int quantize) {
+ int64bits a, b;
+ a = clockCycles();
+ #ifdef VISUAL
+ Sleep(1000/4);
+ #else
+ usleep(1000000/4);
+ #endif
+ b = clockCycles();
+
+ int output = (int)(4*(b-a-140100-450000));
+
+ if (quantize) {
+ // quantize to a known computer CPU speed
+ if (output < 78000000) {
+ output = 75000000;
+ } else if (output < 95000000) {
+ output = 90000000;
+ } else if (output < 110000000) {
+ output = 100000000;
+ } else if (output < 140000000) {
+ output = 133000000;
+ } else if (output < 155000000) {
+ output = 150000000;
+ } else if (output < 180000000) {
+ output = 166000000;
+ } else if (output < 215000000) {
+ output = 200000000;
+ } else if (output < 250000000) {
+ output = 233000000;
+ } else if (output < 280000000) {
+ output = 266000000;
+ } else if (output < 325000000) {
+ output = 300000000;
+ } else if (output < 375000000) {
+ output = 350000000;
+ } else if (output < 425000000) {
+ output = 400000000;
+ } else {
+ output = output;
+ }
+ } // end if quantize
+
+ return output;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::reset -- set the timer to 0.
+//
+
+void SigTimer::reset(void) {
+ offset = clockCycles();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setCpuSpeed -- You can also vary the CPU speed here to cause the
+// getTime function to output different units of time, but the
+// setTicksPerSecond is a more appropriate place to do such a thing.
+//
+
+void SigTimer::setCpuSpeed(int aSpeed) {
+ if (aSpeed <= 0) {
+ std::cerr << "Error: Cannot set the cpu speed to be negative: "
+ << aSpeed << std::endl;
+ exit(1);
+ }
+ cpuSpeed = aSpeed;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setPeriod -- sets the period length of the timer.
+// input value cannot be less than 1.0.
+//
+
+void SigTimer::setPeriod(double aPeriod) {
+ if (aPeriod < 1.0) {
+ std::cerr << "Error: period too small: " << aPeriod << std::endl;
+ exit(1);
+ }
+ period = aPeriod;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setPeriodCount -- adjusts the offset time according
+// to the current period to match the specified period count.
+//
+
+void SigTimer::setPeriodCount(double aCount) {
+ offset = (int64bits)(clockCycles() - aCount * getPeriod() *
+ getCpuSpeed() / getTicksPerSecond());
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setTempo -- sets the period length in terms of
+// beats per minute.
+//
+
+void SigTimer::setTempo(double beatsPerMinute) {
+ if (beatsPerMinute < 1.0) {
+ std::cerr << "Error: tempo is too slow: " << beatsPerMinute << std::endl;
+ exit(1);
+ }
+ double count = getPeriodCount();
+ period = getTicksPerSecond() * 60.0 / beatsPerMinute;
+ setPeriodCount(count);
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::setTicksPerSecond
+//
+
+void SigTimer::setTicksPerSecond(int aTickRate) {
+ if (aTickRate <= 0) {
+ std::cerr << "Error: Cannot set the tick rate to be negative: "
+ << aTickRate << std::endl;
+ exit(1);
+ }
+ ticksPerSecond = aTickRate;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::start
+//
+
+void SigTimer::start(void) {
+ reset();
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::sync
+//
+
+void SigTimer::sync(SigTimer& aTimer) {
+ offset = aTimer.offset;
+}
+
+
+
+//////////////////////////////
+//
+// SigTimer::update -- set the timer start to the next period.
+//
+
+void SigTimer::update(void) {
+ if (getTime() >= getPeriod()) {
+ offset += (int64bits)(getPeriod() * getFactor());
+ }
+}
+
+
+// update(int) will do nothing if the periodCount is greater than
+// than the expired period count
+
+void SigTimer::update(int periodCount) {
+ if (periodCount > expired()) {
+ return;
+ } else {
+ offset += (int64bits)(getPeriod() * getFactor() * periodCount);
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// protected functions:
+//
+
+
+//////////////////////////////
+//
+// SigTimer::getFactor --
+//
+
+double SigTimer::getFactor(void) const {
+ return (double)((double)getCpuSpeed()/(double)getTicksPerSecond());
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Miscellaneous timing functions are located here untill a better
+// place can be found:
+//
+
+void millisleep(int milliseconds) {
+ #ifdef VISUAL
+ Sleep(milliseconds);
+ #else
+ usleep( milliseconds * 1000);
+ #endif
+}
+
+
+void millisleep(float milliseconds) {
+ #ifdef VISUAL
+ // cannot convert to microseconds in Visual C++ yet.
+ // Tell me how and I'll fix the following line
+ Sleep((unsigned long)milliseconds);
+ #else
+ usleep((int)(milliseconds * 1000.0));
+ #endif
+}
+
+
+
+
+// md5sum: b35e9e6a8d6fd16636d7fca5d565f284 - SigTimer.cpp =css= 20030102
diff --git a/src/midiio/src/Voice.cpp b/src/midiio/src/Voice.cpp
new file mode 100644
index 0000000..ed05bce
--- /dev/null
+++ b/src/midiio/src/Voice.cpp
@@ -0,0 +1,334 @@
+//
+// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
+// Creation Date: Sun Oct 11 18:39:14 PDT 1998
+// Last Modified: Sun Oct 11 18:39:18 PDT 1998
+// Filename: ...sig/maint/code/control/Voice/Voice.cpp
+// Web Address: http://www-ccrma.stanford.edu/~craig/improv/src/Voice.cpp
+// Syntax: C++
+//
+// Description: The Voice class is a MIDI output class which keeps
+// track of the last note played in to it. If the last
+// note was not turned off when a new note is played,
+// then the old note will be turned off before the
+// new note is played.
+//
+
+#include "Voice.h"
+
+
+// declare static variables:
+SigTimer Voice::timer;
+
+//////////////////////////////
+//
+// Voice::Voice
+//
+
+Voice::Voice(int aChannel) {
+ chan = oldChan = aChannel;
+ vel = oldVel = key = oldKey = 0;
+}
+
+
+Voice::Voice(const Voice& aVoice) {
+ chan = aVoice.chan;
+ vel = aVoice.vel;
+ key = aVoice.key;
+ oldChan = 0;
+ oldVel = 0;
+ oldKey = 0;
+}
+
+
+Voice::Voice(void) {
+ chan = oldChan = key = oldKey = vel = oldVel = 0;
+}
+
+
+//////////////////////////////
+//
+// Voice::~Voice
+//
+
+Voice::~Voice() {
+ off();
+}
+
+
+
+//////////////////////////////
+//
+// Voice::cont -- use default channel if none specified for
+// the continuous controller message.
+//
+
+void Voice::cont(int controller, int data) {
+ MidiOutput::cont(getChannel(), controller, data);
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getChan -- returns the channel of the voice.
+// Synonym for getChannel.
+//
+
+int Voice::getChan(void) const {
+ return chan;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getChannel -- returs the channel of the voice.
+//
+
+int Voice::getChannel(void) const {
+ return chan;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getKey -- returns the current MIDI key number of the voice.
+// Synonym for getKeynum.
+//
+
+int Voice::getKey(void) const {
+ return key;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getKeynum -- returns the current MIDI key number of the voice.
+//
+
+int Voice::getKeynum(void) const {
+ return key;
+}
+
+
+//////////////////////////////
+//
+// Voice::getOffTime -- returns the last note off message sent
+// out of the voice object
+//
+
+int Voice::getOffTime(void) const {
+ return offTime;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getOnTime -- returns the last note on message sent
+// out of the voice object.
+//
+
+int Voice::getOnTime(void) const {
+ return onTime;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getVel -- returns the current velocity of the MIDI key.
+// Synonym for getVelocity.
+//
+
+int Voice::getVel(void) const {
+ return vel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::getVelocity -- returns the current velocity of the MIDI key.
+//
+
+int Voice::getVelocity(void) const {
+ return vel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::off
+//
+
+void Voice::off(void) {
+ if (status() != 0) {
+ offTime = timer.getTime();
+ MidiOutput::play(oldChan, oldKey, 0);
+ oldVel = 0;
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Voice::pc -- use default channel if none is specified
+//
+
+void Voice::pc(int aTimbre) {
+ MidiOutput::pc(getChannel(), aTimbre);
+}
+
+
+
+//////////////////////////////
+//
+// Voice::play
+//
+
+void Voice::play(int aChannel, int aKeyno, int aVelocity) {
+ off();
+ MidiOutput::play(aChannel, aKeyno, aVelocity);
+ oldChan = aChannel;
+ oldKey = aKeyno;
+ oldVel = aVelocity;
+ setChannel(aChannel);
+ setKeynum(aKeyno);
+ setVelocity(aVelocity);
+
+ if (aVelocity != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+void Voice::play(int aKeyno, int aVelocity) {
+ off();
+ MidiOutput::play(getChannel(), aKeyno, aVelocity);
+ oldChan = getChannel();
+ oldKey = aKeyno;
+ oldVel = aVelocity;
+ setKeynum(aKeyno);
+ setVelocity(aVelocity);
+
+ if (aVelocity != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+void Voice::play(void) {
+ off();
+ MidiOutput::play(getChannel(), getKey(), getVel());
+ oldChan = getChannel();
+ oldKey = getKey();
+ oldVel = getVel();
+
+ if (getVel() != 0) {
+ onTime = timer.getTime();
+ } else {
+ offTime = timer.getTime();
+ }
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setChan -- set the MIDI channel. Synonym for setChannel.
+//
+
+void Voice::setChan(int aChannel) {
+ chan = aChannel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setChannel -- set the MIDI channel of the voice.
+//
+
+void Voice::setChannel(int aChannel) {
+ chan = aChannel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setKey -- set the keynumber of the voice
+// Synonym for setKeyno.
+//
+
+void Voice::setKey(int aKeynum) {
+ key = aKeynum;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setKeynum -- set the keynumber of the voice
+//
+
+void Voice::setKeynum(int aKeynum) {
+ key = aKeynum;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setVel -- set the MIDI velocity of the voice.
+// Synonym for setVelocity.
+//
+
+void Voice::setVel(int aVelocity) {
+ vel = aVelocity;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::setVelocity
+//
+
+void Voice::setVelocity(int aVelocity) {
+ vel = aVelocity;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::status -- returns zero if off or positive if on.
+//
+
+int Voice::status(void) const {
+ return oldVel;
+}
+
+
+
+//////////////////////////////
+//
+// Voice::sustain -- uses default channel if none specified.
+//
+
+void Voice::sustain(int aStatus) {
+ MidiOutput::sustain(getChannel(), aStatus);
+}
+
+
+// md5sum: d02ca41ae3b4e07efe7fedc720e52573 - Voice.cpp =css= 20030102