# libkmid Library API Documentation

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

# midimapper.cc

    00001 /**************************************************************************
    00002
    00003     midimapper.cc  - The midi mapper object
    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 "midimapper.h"
    00027 #include <stdio.h>
    00028 #include <string.h>
    00029 #include <stdlib.h>
    00030 #ifdef HAVE_CONFIG_H
    00031 #include <config.h>
    00032 #endif
    00033
    00034 MidiMapper::MidiMapper(const char *name)
    00035 {
    00036   _ok=1;
    00037   keymaps=NULL;
    00038   _filename=NULL;
    00039   mapPitchBender=0;
    00040   mapExpressionToVolumeEvents=0;
    00041   if ((name==NULL)||(name[0]==0))
    00042   {
    00043     deallocateMaps();
    00044     int i;
    00045     for (i=0;i<16;i++)
    00046     {
    00047       channelmap[i]=i;
    00048       channelPatchForced[i]=-1;
    00049     }
    00050     for (i=0;i<128;i++) patchmap[i]=i;
    00051   }
    00052   else
    00053     loadFile(name);
    00054 }
    00055
    00056 MidiMapper::~MidiMapper()
    00057 {
    00058   if (_filename) free(_filename);
    00059   deallocateMaps();
    00060 }
    00061
    00062 void MidiMapper::deallocateMaps(void)
    00063 {
    00064   int i;
    00065   for (i=0;i<16;i++) channelKeymap[i]=NULL;
    00066   for (i=0;i<128;i++) patchKeymap[i]=NULL;
    00067   Keymap *km;
    00068   while (keymaps!=NULL)
    00069   {
    00070     km=keymaps->next;
    00071     delete keymaps;
    00072     keymaps=km;
    00073   }
    00074 }
    00075
    00076 void MidiMapper::getValue(char *s,char *v)
    00077 {
    00078   char *c=s;
    00079   while ((*c!=0)&&(*c!='=')) c++;
    00080   if (*c==0) v[0]=0;
    00081   else
    00082   {
    00083     c++;
    00084     while (*c!=0)
    00085     {
    00086       *v=*c;
    00087       c++;v++;
    00088     }
    00089     *v=0;
    00090   }
    00091 }
    00092
    00093 void MidiMapper::removeSpaces(char *s)
    00094 {
    00095   char *a=s;
    00096   while ((*a!=0)&&(*a==' ')) a++;
    00097   if (*a==0) {*s=0;return;};
    00098   while (*a!=0)
    00099   {
    00100     while ((*a!=0)&&(*a!=' ')&&(*a!=10)&&(*a!=13))
    00101     {
    00102       *s=*a;
    00103       s++;
    00104       a++;
    00105     }
    00106     while ((*a!=0)&&((*a==' ')||(*a==10)||(*a==13))) a++;
    00107     *s=' ';s++;
    00108     if (*a==0) {*s=0;return;};
    00109   }
    00110   *s=0;
    00111
    00112 }
    00113
    00114 int MidiMapper::countWords(char *s)
    00115 {
    00116   int c=0;
    00117   while (*s!=0)
    00118   {
    00119     if (*s==' ') c++;
    00120     s++;
    00121   }
    00122   return c;
    00123 }
    00124
    00125 void MidiMapper::getWord(char *t,char *s,int w)
    00126 {
    00127   int i=0;
    00128   *t=0;
    00129   while ((*s!=0)&&(i<w))
    00130   {
    00131     if (*s==' ') i++;
    00132     s++;
    00133   }
    00134   while ((*s!=0)&&(*s!=' ')&&(*s!=10)&&(*s!=13))
    00135   {
    00136     *t=*s;
    00137     t++;s++;
    00138   }
    00139   *t=0;
    00140 }
    00141
    00142
    00143 void MidiMapper::loadFile(const char *name)
    00144 {
    00145   _ok=1;
    00146   FILE *fh = fopen(name,"rt");
    00147   if ( fh == NULL ) { _ok = -1; return; };
    00148   char s[101];
    00149   s[0] = 0;
    00150   if ( _filename != NULL ) free(_filename);
    00151   _filename = strdup(name);
    00152 #ifdef MIDIMAPPERDEBUG
    00153   printf("Loading mapper ...\n");
    00154 #endif
    00155   while (!feof(fh))
    00156   {
    00157     s[0]=0;
    00158     while ((!feof(fh))&&((s[0]==0)||(s[0]=='#'))) fgets(s,100,fh);
    00159     if (strncmp(s,"DEFINE",6)==0)
    00160     {
    00161       if (strncmp(&s[7],"PATCHMAP",8)==0) readPatchmap(fh);
    00162       else
    00163         if (strncmp(&s[7],"KEYMAP",6)==0) readKeymap(fh,s);
    00164         else
    00165           if (strncmp(&s[7],"CHANNELMAP",10)==0) readChannelmap(fh);
    00166           else
    00167           {
    00168             printf("ERROR: Unknown DEFINE line in map file\n");
    00169             _ok=0;
    00170           }
    00171       if (_ok==0)
    00172       {
    00173         printf("The midi map file will be ignored\n");
    00174         fclose(fh);
    00175         return;
    00176       }
    00177     }
    00178     else if (strncmp(s,"OPTIONS",7)==0) readOptions(fh);
    00179   }
    00180   fclose(fh);
    00181 }
    00182
    00183 MidiMapper::Keymap *MidiMapper::createKeymap(char *name,uchar use_same_note,uchar note)
    00184 {
    00185   Keymap *km=new Keymap;
    00186   strncpy(km->name, name, KM_NAME_SIZE);
    00187   km->name[KM_NAME_SIZE - 1] = 0;
    00188
    00189   int i;
    00190   if (use_same_note==1)
    00191   {
    00192     for (i=0;i<128;i++)
    00193       km->key[i]=note;
    00194   }
    00195   else
    00196   {
    00197     for (i=0;i<128;i++)
    00198       km->key[i]=i;
    00199   }
    00200   addKeymap(km);
    00201   return km;
    00202 }
    00203
    00204 void MidiMapper::addKeymap(Keymap *newkm)
    00205 {
    00206   Keymap *km=keymaps;
    00207   if (keymaps==NULL)
    00208   {
    00209     keymaps=newkm;
    00210     newkm->next=NULL;
    00211     return;
    00212   }
    00213   while (km->next!=NULL) km=km->next;
    00214   km->next=newkm;
    00215   newkm->next=NULL;
    00216   return;
    00217 }
    00218
    00219 MidiMapper::Keymap *MidiMapper::keymap(char *n)
    00220 {
    00221   Keymap *km=keymaps;
    00222   while ((km!=NULL)&&(strcmp(km->name,n)!=0)) km=km->next;
    00223   return km;
    00224 }
    00225
    00226 void MidiMapper::readOptions(FILE *fh)
    00227 {
    00228 #ifdef MIDIMAPPERDEBUG
    00229   printf("Loading Options ... \n");
    00230 #endif
    00231   char s[101];
    00232   char v[101];
    00233   char t[101];
    00234   int fin=0;
    00235   mapPitchBender=0;
    00236   while (!fin)
    00237   {
    00238     s[0]=0;
    00239     while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
    00240     if (strncmp(s,"PitchBenderRatio",16)==0)
    00241     {
    00242       getValue(s,v);
    00243       removeSpaces(v);
    00244       getWord(t,v,0);
    00245       mapPitchBender=1;
    00246       pitchBenderRatio=atoi(t);
    00247     }
    00248     else if (strncmp(s,"MapExpressionToVolumeEvents",27)==0) mapExpressionToVolumeEvents=1;
    00249     else if (strncmp(s,"END",3)==0)
    00250     {
    00251       fin=1;
    00252     }
    00253     else
    00254     {
    00255       printf("ERROR: Invalid option in OPTIONS section of map file : (%s)\n",s);
    00256       _ok=0;
    00257       return;
    00258     }
    00259   }
    00260 }
    00261
    00262 void MidiMapper::readPatchmap(FILE *fh)
    00263 {
    00264   char s[101];
    00265   char v[101];
    00266   char t[101];
    00267   char name[256]; /* Longer than t and 'AllKeysTo' */
    00268   int i=0;
    00269   int j,w;
    00270 #ifdef MIDIMAPPERDEBUG
    00271   printf("Loading Patch map ... \n");
    00272 #endif
    00273   while (i<128)
    00274   {
    00275     s[0]=0;
    00276     while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
    00277     getValue(s,v);
    00278     removeSpaces(v);
    00279     w=countWords(v);
    00280     j=0;
    00281     patchKeymap[i]=NULL;
    00282     patchmap[i]=i;
    00283     while (j<w)
    00284     {
    00285       getWord(t,v,j);
    00286       if (strcmp(t,"AllKeysTo")==0)
    00287       {
    00288         j++;
    00289         if (j>=w)
    00290         {
    00291           printf("ERROR: Invalid option in PATCHMAP section of map file\n");
    00292           _ok=0;
    00293           return;
    00294         }
    00295         getWord(t,v,j);
    00296         sprintf(name,"AllKeysTo%s",t);
    00297         patchKeymap[i]=createKeymap(name,1,atoi(t));
    00298       }
    00299       else
    00300       {
    00301         patchmap[i]=atoi(t);
    00302       }
    00303       j++;
    00304     }
    00305     i++;
    00306   }
    00307   s[0]=0;
    00308   while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
    00309   if (strncmp(s,"END",3)!=0)
    00310   {
    00311     printf("ERROR: End of section not found in map file\n");
    00312     _ok=0;
    00313     return;
    00314   }
    00315 }
    00316
    00317 void MidiMapper::readKeymap(FILE *fh,char *first_line)
    00318 {
    00319   char s[101];
    00320   char v[101];
    00321 #ifdef MIDIMAPPERDEBUG
    00322   printf("Loading Key map ... %s",first_line);
    00323 #endif
    00324   removeSpaces(first_line);
    00325   getWord(v,first_line,2);
    00326   Keymap *km=new Keymap;
    00327   strncpy(km->name, v, KM_NAME_SIZE);
    00328   km->name[KM_NAME_SIZE - 1] = 0;
    00329
    00330   int i=0;
    00331   while (i<128)
    00332   {
    00333     s[0]=0;
    00334     while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
    00335     getValue(s,v);
    00336     removeSpaces(v);
    00337     km->key[i]=atoi(v);
    00338     i++;
    00339   }
    00340   s[0]=0;
    00341   while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
    00342   if (strncmp(s,"END",3)!=0)
    00343   {
    00344     printf("ERROR: End of section not found in map file\n");
    00345     _ok=0;
    00346     return;
    00347   }
    00348   addKeymap(km);
    00349 }
    00350
    00351 void MidiMapper::readChannelmap(FILE *fh)
    00352 {
    00353   char s[101];
    00354   char v[101];
    00355   char t[101];
    00356   int i=0;
    00357   int w,j;
    00358 #ifdef MIDIMAPPERDEBUG
    00359   printf("Loading Channel map ... \n");
    00360 #endif
    00361   while (i<16)
    00362   {
    00363     s[0]=0;
    00364     while ((s[0]==0)||(s[0]=='#')) fgets(s,100,fh);
    00365     getValue(s,v);
    00366     removeSpaces(v);
    00367     w=countWords(v);
    00368     j=0;
    00369     channelKeymap[i]=NULL;
    00370     channelPatchForced[i]=-1;
    00371     channelmap[i]=i;
    00372     while (j<w)
    00373     {
    00374       getWord(t,v,j);
    00375       if (strcmp(t,"Keymap")==0)
    00376       {
    00377         j++;
    00378         if (j>=w)
    00379         {
    00380           printf("ERROR: Invalid option in CHANNELMAP section of map file\n");
    00381           _ok=0;
    00382           return;
    00383         }
    00384         getWord(t,v,j);
    00385         channelKeymap[i]=keymap(t);
    00386       }
    00387       else if (strcmp(t,"ForcePatch")==0)
    00388       {
    00389         j++;
    00390         if (j>=w)
    00391         {
    00392           printf("ERROR: Invalid option in CHANNELMAP section of map file\n");
    00393           _ok=0;
    00394           return;
    00395         }
    00396         getWord(t,v,j);
    00397         channelPatchForced[i]=atoi(t);
    00398       }
    00399       else
    00400       {
    00401         channelmap[i]=atoi(t);
    00402       }
    00403       j++;
    00404     }
    00405     i++;
    00406   }
    00407   s[0]=0;
    00408   while ((s[0]==0)||(s[0]=='#')||(s[0]==10)||(s[0]==13)) fgets(s,100,fh);
    00409   if (strncmp(s,"END",3)!=0)
    00410   {
    00411     printf("END of section not found in map file\n");
    00412     _ok=0;
    00413     return;
    00414   }
    00415
    00416 }
    00417
    00418 const char *MidiMapper::filename(void)
    00419 {
    00420   return (_filename)? _filename : "";
    00421 }
    00422
    00423 uchar MidiMapper::key(uchar chn,uchar pgm, uchar note)
    00424 {
    00425   uchar notemapped=note;
    00426   if (patchKeymap[pgm]!=NULL) notemapped=patchKeymap[pgm]->key[note];
    00427   if (channelKeymap[chn]!=NULL) notemapped=channelKeymap[chn]->key[note];
    00428   return notemapped;
    00429 }
    00430
    00431 uchar MidiMapper::patch(uchar chn,uchar pgm)
    00432 {
    00433   return (channelPatchForced[chn] == -1) ?
    00434     patchmap[pgm] : (uchar)channelPatchForced[chn] ;
    00435 }
    00436
    00437 void MidiMapper::pitchBender(uchar ,uchar &lsb,uchar &msb)
    00438 {
    00439   if (mapPitchBender)
    00440   {
    00441     short pbs=((short)msb<<7) | (lsb & 0x7F);
    00442     pbs=pbs-0x2000;
    00443     short pbs2=(((long)pbs*pitchBenderRatio)/4096);
    00444 #ifdef MIDIMAPPERDEBUG
    00445     printf("Pitch Bender (%d): %d -> %d \n",chn,pbs,pbs2);
    00446 #endif
    00447     pbs2=pbs2+0x2000;
    00448     lsb=pbs2 & 0x7F;
    00449     msb=(pbs2 >> 7)&0x7F;
    00450   }
    00451 }
    00452
    00453 void MidiMapper::controller(uchar ,uchar &ctl, uchar &)
    00454 {
    00455   if ((mapExpressionToVolumeEvents)&&(ctl==11)) ctl=7;
    00456 }

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