From ceac394c2133d44e81db2eb633ff54a9ad6ce7c5 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 10 Nov 2005 05:52:11 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r3865, which included commits to RCS files with non-trunk default branches. svn path=/trunk/extensions/gripd/; revision=3866 --- src/midiio/src/Sequencer_oss.cpp | 809 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 809 insertions(+) create mode 100644 src/midiio/src/Sequencer_oss.cpp (limited to 'src/midiio/src/Sequencer_oss.cpp') 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 +// 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 + + +#include +#include +#include +#include +#include +#include +#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()) { + 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= 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 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 -- cgit v1.2.1