//------------------------------------------------------------------------- // Filename: ossmidi.cc // Version: $Id: ossmidi.cc,v 1.1.2.2 1999/06/09 10:14:04 erik Exp $ // Copyright: Copyright (C) 1999, Erik Mouw (J.A.K.Mouw@its.tudelft.nl) // Author: Erik Mouw // Description: Play MIDI events on an OSS MIDI interface // Created at: Mon May 24 17:43:43 1999 // Modified by: Erik Mouw // Modified at: Wed Jun 9 12:11:33 1999 //------------------------------------------------------------------------- // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #ident "$Id: ossmidi.cc,v 1.1.2.2 1999/06/09 10:14:04 erik Exp $" #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include using namespace std; #include #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_MALLOC_H # include # else # ifndef NULL # define NULL ((void *)0) # endif # endif #endif #ifdef HAVE_UNISTD_H # include #endif #include #include #ifdef HAVE_FCNTL_H # include #endif #ifdef HAVE_LINUX_SOUNDCARD_H # include #else # include #endif #ifdef HAVE_SYS_IOCTL_H # include #endif #include "ossmidi.hh" #ifndef HAVE_STRERROR extern "C" char *strerror(int errnum); #endif #ifndef HAVE_STRDUP extern "C" char *strdup(const char *s); #endif // Sequence buffer size SEQ_DEFINEBUF(128); typedef struct { char *filename; int fd; int count; } ossDevice; static const int numOssDevices = 16; // should be enough, I think static ossDevice openedDevices[numOssDevices] = { {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0} }; static int openOssDevice(char *filename) { int i; int index = -1; int fd; #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif assert(filename != 0); // find out if is it already opened for(i = 0; i < numOssDevices; i++) { if((openedDevices[i].filename != 0) && (strcmp(openedDevices[i].filename, filename) == 0)) { index = i; break; } } if(index != -1) { openedDevices[index].count++; return(openedDevices[index].fd); } // find a new device for(i = 0; i < numOssDevices; i++) { if(openedDevices[i].filename == 0) { index = i; break; } } // no new OSS device can be opened if(index == -1) return(-1); // try to open device fd = open(filename, O_RDWR); if(fd == -1) { cerr<< __PRETTY_FUNCTION__<< ": can't open device '"<< filename<< "': "<< strerror(errno)<< endl; return(-1); } else { openedDevices[index].filename = strdup(filename); openedDevices[index].fd = fd; openedDevices[index].count = 1; return(fd); } } static bool closeOssDevice(char *filename) { int i; int index = -1; #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif assert(filename != 0); // find the device for(i = 0; i < numOssDevices; i++) { if((openedDevices[i].filename != 0) && (strcmp(openedDevices[i].filename, filename) == 0)) { index = i; break; } } // not found? if(index == -1) { #ifdef MUSICA_DEBUG cerr<< __FUNCTION__<< ": can't find device '"<< filename<< "'"<< endl; #endif return(false); } // lower refcount openedDevices[index].count --; if(openedDevices[index].count == 0) { if(close(openedDevices[index].fd) < 0) { cerr<< __PRETTY_FUNCTION__<< ": can't close device '"<< filename<< "'"<< strerror(errno)<< endl; } free(openedDevices[index].filename); openedDevices[index].filename = 0; openedDevices[index].fd = -1; openedDevices[index].count = 0; } return(true); } // --- ossSynth class ---------------------------------------------------- static const char *ossSynthDeviceType = "oss-synth"; ossSynth::ossSynth(const char *theName) : midiDevice(theName) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif device = 0; fd = -1; deviceNo = -1; type = ossSynthDeviceType; } ossSynth::~ossSynth(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif close(); if(device != 0) free(device); } void ossSynth::setDevice(char *filename, int number) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif assert(filename != 0); close(); if(device != 0) free(device); device = strdup(filename); deviceNo = number; } bool ossSynth::open(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif if(device == 0) { return(false); } fd = openOssDevice(device); if(fd == -1) return(false); else return(true); } bool ossSynth::close(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif if(device == 0) return(false); fd = -1; return(closeOssDevice(device)); } void ossSynth::noteOn(int channel, int key, int velocity) { } void ossSynth::noteOff(int channel, int key, int velocity) { } void ossSynth::keyPressure(int channel, int key, int pressure) { } void ossSynth::channelPressure(int channel, int pressure) { } void ossSynth::pitchBend(int channel, int fine, int coarse) { } void ossSynth::controlChange(int channel, int controller, int value) { } void ossSynth::programChange(int channel, int program) { } void ossSynth::allNoteOff(void) { } void ossSynth::systemReset(void) { } // --- ossSequencer class ------------------------------------------------ static const char *ossSequencerDeviceType = "oss-sequencer"; void ossSequencer::seqbuf_dump() { if (_seqbufptr) if (write(fd, _seqbuf, _seqbufptr) == -1) { cerr<< __PRETTY_FUNCTION__<< ": can't write:"<< strerror(errno)<< endl; exit(-1); } _seqbufptr = 0; } ossSequencer::ossSequencer(const char *theName) : midiDevice(theName) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif device = 0; fd = -1; deviceNo = -1; type = ossSequencerDeviceType; } ossSequencer::~ossSequencer(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif close(); if(device != 0) free(device); } void ossSequencer::setDevice(char *filename, int number) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif assert(filename != 0); close(); if(device != 0) free(device); device = strdup(filename); deviceNo = number; } bool ossSequencer::open(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif if(device == 0) { return(false); } fd = openOssDevice(device); if(fd == -1) return(false); else return(true); } bool ossSequencer::close(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif fd = -1; if(device == 0) return(false); return(closeOssDevice(device)); } void ossSequencer::noteOn(int channel, int key, int velocity) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, key, velocity) = ("<< channel<< ", "<< key<< ", "<< velocity<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_NOTEON | channel); SEQ_MIDIOUT(deviceNo, key); SEQ_MIDIOUT(deviceNo, velocity); SEQ_DUMPBUF(); } void ossSequencer::noteOff(int channel, int key, int velocity) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, key, velocity) = ("<< channel<< ", "<< key<< ", "<< velocity<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_NOTEOFF | channel); SEQ_MIDIOUT(deviceNo, key); SEQ_MIDIOUT(deviceNo, velocity); SEQ_DUMPBUF(); } void ossSequencer::keyPressure(int channel, int key, int pressure) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, key, pressure) = ("<< channel<< ", "<< key<< ", "<< pressure<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_KEY_PRESSURE | channel); SEQ_MIDIOUT(deviceNo, key); SEQ_MIDIOUT(deviceNo, pressure); SEQ_DUMPBUF(); } void ossSequencer::channelPressure(int channel, int pressure) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, pressure) = ("<< channel<< ", "<< pressure<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_CHN_PRESSURE | channel); SEQ_MIDIOUT(deviceNo, pressure); SEQ_DUMPBUF(); } void ossSequencer::pitchBend(int channel, int fine, int coarse) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, fine, coarse) = ("<< channel<< ", "<< fine<< ", "<< coarse<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_PITCH_BEND | channel); SEQ_MIDIOUT(deviceNo, fine); SEQ_MIDIOUT(deviceNo, coarse); SEQ_DUMPBUF(); } void ossSequencer::controlChange(int channel, int controller, int value) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, controller, value) = ("<< channel<< ", "<< controller<< ", "<< value<< ")"<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_CTL_CHANGE | channel); SEQ_MIDIOUT(deviceNo, controller); SEQ_MIDIOUT(deviceNo, value); SEQ_DUMPBUF(); } void ossSequencer::programChange(int channel, int program) { #ifdef MIDI_DEBUG cout<< __FUNCTION__<< "(channel, program) = ("<< channel<< ", "<< program<< ")"<< endl; #endif #ifdef MUSICA_DEBUG cerr<< __FUNCTION__<< ": "<< getType()<< "("<< getName()<< ") ch# "<< channel<< " prgm# "<< program<< endl; #endif SEQ_MIDIOUT(deviceNo, MIDI_PGM_CHANGE | channel); SEQ_MIDIOUT(deviceNo, program); SEQ_DUMPBUF(); } void ossSequencer::allNoteOff(void) { } void ossSequencer::systemReset(void) { } // --- ossMidi class ----------------------------------------------------- static const char *ossMidiDeviceType = "oss-midi"; ossMidi::ossMidi(const char *theName) : midiDevice(theName) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif type = ossMidiDeviceType; } ossMidi::~ossMidi(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif } void ossMidi::setDevice(char *filename) { } bool ossMidi::open(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif return(false); } bool ossMidi::close(void) { #ifdef MUSICA_DEBUG cerr<< __PRETTY_FUNCTION__<< endl; #endif return(false); } void ossMidi::noteOn(int channel, int key, int velocity) { } void ossMidi::noteOff(int channel, int key, int velocity) { } void ossMidi::keyPressure(int channel, int key, int pressure) { } void ossMidi::channelPressure(int channel, int pressure) { } void ossMidi::pitchBend(int channel, int fine, int coarse) { } void ossMidi::controlChange(int channel, int controller, int value) { } void ossMidi::programChange(int channel, int program) { } void ossMidi::allNoteOff(void) { } void ossMidi::systemReset(void) { }