# libkmid Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# midiout.cc

    00001 /**************************************************************************
    00002
    00003     midiout.cc   - class midiOut which handles external midi devices
    00004     This file is part of LibKMid 0.9.5
    00005     Copyright (C) 1997,98,99,2000  Antonio Larrosa Jimenez
    00006     LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libkmid.html
    00007
    00008     This library is free software; you can redistribute it and/or
    00009     modify it under the terms of the GNU Library General Public
    00010     License as published by the Free Software Foundation; either
    00011     version 2 of the License, or (at your option) any later version.
    00012
    00013     This library is distributed in the hope that it will be useful,
    00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016     Library General Public License for more details.
    00017
    00018     You should have received a copy of the GNU Library General Public License
    00019     along with this library; see the file COPYING.LIB.  If not, write to
    00020     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021     Boston, MA 02111-1307, USA.
    00022
    00023     Send comments and bug fixes to Antonio Larrosa <larrosa@kde.org>
    00024
    00025 ***************************************************************************/
    00026 #include "midiout.h"
    00027 #include <unistd.h>
    00028 #include <fcntl.h>
    00029 #include <stdio.h>
    00030 #include "sndcard.h"
    00031 #include <errno.h>
    00032 #include <string.h>
    00033 #include <stdlib.h>
    00034 #include <sys/param.h>
    00035 #include "midispec.h"
    00036 #include "alsaout.h"
    00037
    00038 #ifdef HAVE_CONFIG_H
    00039 #include <config.h>
    00040 #endif
    00041
    00042 #include <sys/ioctl.h>
    00043
    00044 SEQ_USE_EXTBUF();
    00045
    00046 MidiOut::MidiOut(int d)
    00047 {
    00048   seqfd = -1;
    00049   devicetype=KMID_EXTERNAL_MIDI;
    00050   device= d;
    00051   volumepercentage=100;
    00052   map=new MidiMapper(NULL);
    00053   if (map==NULL) { printfdebug("ERROR : midiOut : Map is NULL\n"); return; };
    00054   _ok=1;
    00055 }
    00056
    00057 MidiOut::~MidiOut()
    00058 {
    00059   delete map;
    00060   closeDev();
    00061 }
    00062
    00063 void MidiOut::openDev (int sqfd)
    00064 {
    00065 #ifdef HAVE_OSS_SUPPORT
    00066   _ok=1;
    00067   seqfd=sqfd;
    00068   if (seqfd==-1)
    00069   {
    00070     printfdebug("ERROR: Could not open /dev/sequencer\n");
    00071     _ok=0;
    00072     return;
    00073   }
    00074 #endif
    00075 }
    00076
    00077 void MidiOut::closeDev (void)
    00078 {
    00079   if (!ok()) return;
    00080 //  if (deviceType()!=KMID_ALSA) allNotesOff();
    00081   SEQ_STOP_TIMER();
    00082   SEQ_DUMPBUF();
    00083   seqfd=-1;
    00084 }
    00085
    00086 void MidiOut::initDev (void)
    00087 {
    00088 #ifdef HAVE_OSS_SUPPORT
    00089   int chn;
    00090   if (!ok()) return;
    00091   uchar gm_reset[5]={0x7e, 0x7f, 0x09, 0x01, 0xf7};
    00092   sysex(gm_reset, sizeof(gm_reset));
    00093   for (chn=0;chn<16;chn++)
    00094   {
    00095     chnmute[chn]=0;
    00096     chnPatchChange(chn,0);
    00097     chnPressure(chn,127);
    00098     chnPitchBender(chn, 0x00, 0x40);
    00099     chnController(chn, CTL_MAIN_VOLUME,110*volumepercentage);
    00100     chnController(chn, CTL_EXT_EFF_DEPTH, 0);
    00101     chnController(chn, CTL_CHORUS_DEPTH, 0);
    00102     chnController(chn, 0x4a, 127);
    00103   }
    00104 #endif
    00105 }
    00106
    00107 void MidiOut::setMidiMapper(MidiMapper *_map)
    00108 {
    00109   delete map;
    00110   map=_map;
    00111 }
    00112
    00113 void MidiOut::noteOn  (uchar chn, uchar note, uchar vel)
    00114 {
    00115   if (vel==0)
    00116   {
    00117     noteOff(chn,note,vel);
    00118   }
    00119   else
    00120   {
    00121     SEQ_MIDIOUT(device, MIDI_NOTEON + map->channel(chn));
    00122     SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
    00123     SEQ_MIDIOUT(device, vel);
    00124   }
    00125 #ifdef MIDIOUTDEBUG
    00126   printfdebug("Note ON >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
    00127 #endif
    00128 }
    00129
    00130 void MidiOut::noteOff (uchar chn, uchar note, uchar vel)
    00131 {
    00132   SEQ_MIDIOUT(device, MIDI_NOTEOFF + map->channel(chn));
    00133   SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
    00134   SEQ_MIDIOUT(device, vel);
    00135 #ifdef MIDIOUTDEBUG
    00136   printfdebug("Note OFF >\t chn : %d\tnote : %d\tvel: %d\n",chn,note,vel);
    00137 #endif
    00138 }
    00139
    00140 void MidiOut::keyPressure (uchar chn, uchar note, uchar vel)
    00141 {
    00142   SEQ_MIDIOUT(device, MIDI_KEY_PRESSURE + map->channel(chn));
    00143   SEQ_MIDIOUT(device, map->key(chn,chnpatch[chn],note));
    00144   SEQ_MIDIOUT(device, vel);
    00145 }
    00146
    00147 void MidiOut::chnPatchChange (uchar chn, uchar patch)
    00148 {
    00149 #ifdef MIDIOUTDEBUG
    00150   printfdebug("PATCHCHANGE [%d->%d] %d -> %d\n",
    00151       chn,map->channel(chn),patch,map->patch(chn,patch));
    00152 #endif
    00153   SEQ_MIDIOUT(device, MIDI_PGM_CHANGE + map->channel(chn));
    00154   SEQ_MIDIOUT(device, map->patch(chn,patch));
    00155   chnpatch[chn]=patch;
    00156 }
    00157
    00158 void MidiOut::chnPressure (uchar chn, uchar vel)
    00159 {
    00160   SEQ_MIDIOUT(device, MIDI_CHN_PRESSURE + map->channel(chn));
    00161   SEQ_MIDIOUT(device, vel);
    00162
    00163   chnpressure[chn]=vel;
    00164 }
    00165
    00166 void MidiOut::chnPitchBender(uchar chn,uchar lsb, uchar msb)
    00167 {
    00168   SEQ_MIDIOUT(device, MIDI_PITCH_BEND + map->channel(chn));
    00169   /*
    00170 #ifdef AT_HOME
    00171   short pbs=((short)msb<<7) | (lsb & 0x7F);
    00172   pbs=pbs-0x2000;
    00173   short pbs2=(((long)pbs*672)/4096);
    00174   printfdebug("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2);
    00175   pbs2=pbs2+0x2000;
    00176   lsb=pbs2 & 0x7F;
    00177   msb=(pbs2 >> 7)&0x7F;
    00178 #endif
    00179    */
    00180   map->pitchBender(chn,lsb,msb);
    00181   SEQ_MIDIOUT(device, lsb);
    00182   SEQ_MIDIOUT(device, msb);
    00183   chnbender[chn]=(msb << 8) | (lsb & 0xFF);
    00184 }
    00185
    00186 void MidiOut::chnController (uchar chn, uchar ctl, uchar v)
    00187 {
    00188   SEQ_MIDIOUT(device, MIDI_CTL_CHANGE + map->channel(chn));
    00189 #ifdef AT_HOME
    00190   if (ctl==11) ctl=7;
    00191 #endif
    00192   map->controller(chn,ctl,v);
    00193   if ((ctl==11)||(ctl==7))
    00194   {
    00195     v=(v*volumepercentage)/100;
    00196     if (v>127) v=127;
    00197   }
    00198
    00199   SEQ_MIDIOUT(device, ctl);
    00200   SEQ_MIDIOUT(device, v);
    00201
    00202   chncontroller[chn][ctl]=v;
    00203 }
    00204
    00205 void MidiOut::sysex(uchar *data, ulong size)
    00206 {
    00207   ulong i=0;
    00208   SEQ_MIDIOUT(device, MIDI_SYSTEM_PREFIX);
    00209   while (i<size)
    00210   {
    00211     SEQ_MIDIOUT(device, *data);
    00212     data++;
    00213     i++;
    00214   }
    00215 #ifdef MIDIOUTDEBUG
    00216   printfdebug("sysex\n");
    00217 #endif
    00218 }
    00219
    00220 void MidiOut::allNotesOff (void)
    00221 {
    00222   for (int i=0; i<16; i++)
    00223   {
    00224     chnController(i, 0x78, 0);
    00225     chnController(i, 0x79, 0);
    00226   };
    00227   sync(1);
    00228 }
    00229
    00230 void MidiOut::channelSilence (uchar chn)
    00231 {
    00232   uchar i;
    00233   for ( i=0; i<127; i++)
    00234   {
    00235     noteOff(chn,i,0);
    00236   };
    00237   sync();
    00238 }
    00239
    00240 void MidiOut::channelMute(uchar chn, int a)
    00241 {
    00242   if (a==1)
    00243   {
    00244     chnmute[chn]=a;
    00245     channelSilence(chn);
    00246   }
    00247   else if (a==0)
    00248   {
    00249     chnmute[chn]=a;
    00250   }
    00251   /*  else ignore the call to this function */
    00252 }
    00253
    00254 void MidiOut::seqbuf_dump (void)
    00255 {
    00256 #ifdef HAVE_OSS_SUPPORT
    00257   if (_seqbufptr && seqfd!=-1 && seqfd!=0)
    00258     if (write (seqfd, _seqbuf, _seqbufptr) == -1)
    00259     {
    00260       printfdebug("Error writing to /dev/sequencer in MidiOut::seq_buf_dump\n");
    00261       perror ("write /dev/sequencer in seqBufDump\n");
    00262       exit (-1);
    00263     }
    00264   _seqbufptr = 0;
    00265 #endif
    00266 }
    00267
    00268 void MidiOut::seqbuf_clean(void)
    00269 {
    00270 #ifdef HAVE_OSS_SUPPORT
    00271   _seqbufptr=0;
    00272 #endif
    00273 }
    00274
    00275 const char *MidiOut::midiMapFilename(void)
    00276 {
    00277   return (map!=NULL) ? map->filename() : "";
    00278 }
    00279
    00280 const char * MidiOut::deviceName(void) const
    00281 {
    00282   switch (deviceType())
    00283   {
    00284     case (KMID_EXTERNAL_MIDI) : return "External Midi";
    00285     case (KMID_SYNTH) : return "Synth";
    00286     case (KMID_FM) : return "FM";
    00287     case (KMID_GUS) : return "GUS";
    00288     case (KMID_AWE) : return "AWE";
    00289     case (KMID_ALSA) : return reinterpret_cast<const AlsaOut *>(this)->deviceName();
    00290   }
    00291   return "Unknown";
    00292 }
    00293
    00294 void MidiOut::sync(int i)
    00295 {
    00296   if (deviceType()==KMID_ALSA) { // XXX : sync should be virtual after next bic
    00297      reinterpret_cast<AlsaOut *>(this)->sync(i);
    00298      return;
    00299   }
    00300   SEQ_DUMPBUF();
    00301 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:28:29 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001