// // 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 "Sequencer_oss.h" #include #include #include #include #include #include #ifndef OLDCPP #include using namespace std; #else #include #endif // 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) { cerr << "Unusual class instatiation count: " << class_count << 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) { cerr << "Unusual class instatiation count: " << class_count << 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(ostream& out, const char* initial) { for (int i=0; i= getNumInputs()) { cerr << "Error: " << aDevice << " is greater than max in (" << getNumInputs() << ")" << 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()) { cerr << "Error: " << aDevice << " is greater than max out (" << getNumOutputs() << ")" << 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()) { cerr << "Error: " << aDevice << " is greater than max in (" << getNumInputs() << ")" << 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()) { cerr << "Error: " << aDevice << " is greater than max in (" << getNumInputs() << ")" << endl; exit(1); } return indevtype[aDevice]; } ////////////////////////////// // // Sequencer_oss::getOutDeviceValue -- // int Sequencer_oss::getOutDeviceValue(int aDevice) const { if (aDevice >= getNumOutputs()) { cerr << "Error: " << aDevice << " is greater than max out (" << getNumOutputs() << ")" << 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()) { cerr << "Error: " << aDevice << " is greater than max out (" << getNumOutputs() << ")" << 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) { cerr << "Error: expecting MIDI data but got MIDI command: " << aByte << 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: cerr << "Cannot handle 0xf0 commands yet" << endl; exit(1); break; default: cerr << "Error: unknown MIDI command" << 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: cerr << "Unknown Common MIDI message" << 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: 71936724a48afa7b57a2cb5edebc2290 Sequencer_oss.cpp [20050403]