libkmid Library API Documentation

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 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:59 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001