timidity_common.cpp

Go to the documentation of this file.
00001 /*
00002 
00003     TiMidity -- Experimental MIDI to WAVE converter
00004     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020    common.c
00021 
00022    */
00023 
00024 #include "pent_include.h"
00025 
00026 #ifdef USE_TIMIDITY_MIDI
00027 
00028 #include <cstdio>
00029 #include <cstdlib>
00030 #include <cstring>
00031 
00032 #ifndef _WIN32_WCE
00033 #include <cerrno>
00034 #else
00035 static int errno = 0;
00036 static char *strerror(int _errno) {
00037         return "";
00038 }
00039 #endif
00040 #include "timidity.h"
00041 #include "timidity_common.h"
00042 #include "timidity_output.h"
00043 #include "timidity_controls.h"
00044 
00045 #ifdef NS_TIMIDITY
00046 namespace NS_TIMIDITY {
00047 #endif
00048 
00049 /* I guess "rb" should be right for any libc */
00050 #define OPEN_MODE "rb"
00051 
00052 char current_filename[1024];
00053 
00054 #ifdef DEFAULT_TIMIDITY_PATH
00055     /* The paths in this list will be tried whenever we're reading a file */
00056     static PathList defaultpathlist={DEFAULT_TIMIDITY_PATH,0};
00057     static PathList *pathlist=&defaultpathlist; /* This is a linked list */
00058 #else
00059     static PathList *pathlist=0;
00060 #endif
00061 
00062 /* Try to open a file for reading. If the filename ends in one of the 
00063    defined compressor extensions, pipe the file through the decompressor */
00064 static FILE *try_to_open(char *name, int decompress, int noise_mode)
00065 {
00066   FILE *fp;
00067 
00068   fp=fopen(name, OPEN_MODE); /* First just check that the file exists */
00069 
00070   if (!fp)
00071     return 0;
00072 
00073 #ifdef DECOMPRESSOR_LIST
00074   if (decompress)
00075     {
00076       int l,el;
00077       static char *decompressor_list[] = DECOMPRESSOR_LIST, **dec;
00078       char tmp[1024], tmp2[1024], *cp, *cp2;
00079       /* Check if it's a compressed file */ 
00080       l=strlen(name);
00081       for (dec=decompressor_list; *dec; dec+=2)
00082         {
00083           el=strlen(*dec);
00084           if ((el>=l) || (strcmp(name+l-el, *dec)))
00085             continue;
00086 
00087           /* Yes. Close the file, open a pipe instead. */
00088           fclose(fp);
00089 
00090           /* Quote some special characters in the file name */
00091           cp=name;
00092           cp2=tmp2;
00093           while (*cp)
00094             {
00095               switch(*cp)
00096                 {
00097                 case '\'':
00098                 case '\\':
00099                 case ' ':
00100                 case '`':
00101                 case '!':
00102                 case '"':
00103                 case '&':
00104                 case ';':
00105                   *cp2++='\\';
00106                 }
00107               *cp2++=*cp++;
00108             }
00109           *cp2=0;
00110 
00111           sprintf(tmp, *(dec+1), tmp2);
00112           fp=popen(tmp, "r");
00113           break;
00114         }
00115     }
00116 #endif
00117   
00118   return fp;
00119 }
00120 
00121 /* This is meant to find and open files for reading, possibly piping
00122    them through a decompressor. */
00123 FILE *open_file(const char *name, int decompress, int noise_mode)
00124 {
00125   FILE *fp;
00126   PathList *plp=pathlist;
00127   int l;
00128 
00129   if (!name || !(*name))
00130     {
00131       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Attempted to open nameless file.");
00132       return 0;
00133     }
00134 
00135   /* First try the given name */
00136 
00137   strncpy(current_filename, name, 1023);
00138   current_filename[1023]='\0';
00139 
00140   ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
00141   if ((fp=try_to_open(current_filename, decompress, noise_mode)))
00142     return fp;
00143 
00144 #ifdef ENOENT
00145   if (noise_mode && (errno != ENOENT))
00146     {
00147       ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
00148            current_filename, strerror(errno));
00149       return 0;
00150     }
00151 #endif
00152   
00153 #ifndef __WIN32__
00154   if (name[0] != PATH_SEP)
00155 #else
00156   if (name[0] != '\\' && name[0] != '/' && name[1] != ':')
00157 #endif
00158     while (plp)  /* Try along the path then */
00159       {
00160         *current_filename=0;
00161         l=static_cast<int>(strlen(plp->path));
00162         if(l)
00163           {
00164             strcpy(current_filename, plp->path);
00165 #ifndef __WIN32__
00166             if(current_filename[l-1]!=PATH_SEP)
00167 #else
00168             if(current_filename[l-1]!='\\' && current_filename[l-1]!='/')
00169 #endif
00170               strcat(current_filename, PATH_STRING);
00171           }
00172         strcat(current_filename, name);
00173         ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
00174         if ((fp=try_to_open(current_filename, decompress, noise_mode)))
00175           return fp;
00176 #ifdef ENOENT
00177         if (noise_mode && (errno != ENOENT))
00178           {
00179             ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
00180                  current_filename, strerror(errno));
00181             return 0;
00182           }
00183 #endif
00184         plp=plp->next;
00185       }
00186   
00187   /* Nothing could be opened. */
00188 
00189   *current_filename=0;
00190   
00191   if (noise_mode>=2)
00192     ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name, strerror(errno));
00193   
00194   return 0;
00195 }
00196 
00197 /* This closes files opened with open_file */
00198 void close_file(FILE *fp)
00199 {
00200 #ifdef DECOMPRESSOR_LIST
00201   if (pclose(fp)) /* Any better ideas? */
00202 #endif
00203     fclose(fp);
00204 }
00205 
00206 /* This is meant for skipping a few bytes in a file or fifo. */
00207 void skip(FILE *fp, size_t len)
00208 {
00209   size_t c;
00210   char tmp[1024];
00211   while (len>0)
00212     {
00213       c=len;
00214       if (c>1024) c=1024;
00215       len-=c;
00216       if (c!=fread(tmp, 1, c, fp))
00217         ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: skip: %s",
00218              current_filename, strerror(errno));
00219     }
00220 }
00221 
00222 /* This'll allocate memory or die. */
00223 void *safe_malloc(size_t count)
00224 {
00225   void *p;
00226   if (count > (1<<21))
00227     {
00228       ctl->cmsg(CMSG_FATAL, VERB_NORMAL, 
00229            "Strange, I feel like allocating %d bytes. This must be a bug.",
00230            count);
00231     }
00232   else if ((p=malloc(count)))
00233     return p;
00234   else
00235     ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count);
00236 
00237   ctl->close();
00238   exit(10);
00239   return(NULL);
00240 }
00241 
00242 /* This adds a directory to the path list */
00243 void add_to_pathlist(char *s)
00244 {
00245   PathList *plp=safe_Malloc<PathList>();
00246   strcpy((plp->path=safe_Malloc<char>(strlen(s)+1)),s);
00247   plp->next=pathlist;
00248   pathlist=plp;
00249 }
00250 
00251 #ifdef NS_TIMIDITY
00252 };
00253 #endif
00254 
00255 #endif //USE_TIMIDITY_MIDI

Generated on Fri Jul 27 22:27:43 2007 for pentagram by  doxygen 1.4.7