libkmid Library API Documentation

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 }
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