timidity/common.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 01 Jun 2013 22:30:04 -0700
changeset 627 438fb12df34f
parent 530 a74d68325094
child 755 7c9cfb3bf040
permissions -rw-r--r--
Updated iOS project to include OGG support directly
slouken@0
     1
/*
slouken@0
     2
    TiMidity -- Experimental MIDI to WAVE converter
slouken@0
     3
    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
slouken@0
     4
slouken@0
     5
    This program is free software; you can redistribute it and/or modify
slouken@518
     6
    it under the terms of the Perl Artistic License, available in COPYING.
slouken@518
     7
 */
slouken@0
     8
slouken@0
     9
#include <stdio.h>
slouken@0
    10
#include <stdlib.h>
slouken@0
    11
#include <string.h>
slouken@0
    12
slouken@0
    13
#include <errno.h>
slouken@0
    14
#include "config.h"
slouken@0
    15
#include "common.h"
slouken@0
    16
#include "output.h"
slouken@319
    17
#include "ctrlmode.h"
slouken@0
    18
slouken@0
    19
/* I guess "rb" should be right for any libc */
slouken@0
    20
#define OPEN_MODE "rb"
slouken@0
    21
icculus@449
    22
char current_filename[PATH_MAX];
slouken@0
    23
patmandin@264
    24
static PathList *pathlist=NULL;
slouken@0
    25
slouken@0
    26
/* Try to open a file for reading. If the filename ends in one of the 
slouken@0
    27
   defined compressor extensions, pipe the file through the decompressor */
slouken@433
    28
static FILE *try_to_open(const char *name, int decompress, int noise_mode)
slouken@0
    29
{
slouken@0
    30
  FILE *fp;
slouken@0
    31
slouken@0
    32
  fp=fopen(name, OPEN_MODE); /* First just check that the file exists */
slouken@0
    33
slouken@0
    34
  if (!fp)
slouken@0
    35
    return 0;
slouken@0
    36
slouken@0
    37
#ifdef DECOMPRESSOR_LIST
slouken@0
    38
  if (decompress)
slouken@0
    39
    {
slouken@0
    40
      int l,el;
slouken@0
    41
      static char *decompressor_list[] = DECOMPRESSOR_LIST, **dec;
slouken@433
    42
      const char *cp;
icculus@449
    43
      char tmp[PATH_MAX], tmp2[PATH_MAX], *cp2;
slouken@0
    44
      /* Check if it's a compressed file */ 
slouken@0
    45
      l=strlen(name);
slouken@0
    46
      for (dec=decompressor_list; *dec; dec+=2)
slouken@0
    47
	{
slouken@0
    48
	  el=strlen(*dec);
slouken@0
    49
	  if ((el>=l) || (strcmp(name+l-el, *dec)))
slouken@0
    50
	    continue;
slouken@0
    51
slouken@0
    52
	  /* Yes. Close the file, open a pipe instead. */
slouken@0
    53
	  fclose(fp);
slouken@0
    54
slouken@0
    55
	  /* Quote some special characters in the file name */
slouken@0
    56
	  cp=name;
slouken@0
    57
	  cp2=tmp2;
slouken@0
    58
	  while (*cp)
slouken@0
    59
	    {
slouken@0
    60
	      switch(*cp)
slouken@0
    61
		{
slouken@0
    62
		case '\'':
slouken@0
    63
		case '\\':
slouken@0
    64
		case ' ':
slouken@0
    65
		case '`':
slouken@0
    66
		case '!':
slouken@0
    67
		case '"':
slouken@0
    68
		case '&':
slouken@0
    69
		case ';':
slouken@0
    70
		  *cp2++='\\';
slouken@0
    71
		}
slouken@0
    72
	      *cp2++=*cp++;
slouken@0
    73
	    }
slouken@0
    74
	  *cp2=0;
slouken@0
    75
slouken@0
    76
	  sprintf(tmp, *(dec+1), tmp2);
slouken@0
    77
	  fp=popen(tmp, "r");
slouken@0
    78
	  break;
slouken@0
    79
	}
slouken@0
    80
    }
slouken@0
    81
#endif
slouken@0
    82
  
slouken@0
    83
  return fp;
slouken@0
    84
}
slouken@0
    85
slouken@0
    86
/* This is meant to find and open files for reading, possibly piping
slouken@0
    87
   them through a decompressor. */
slouken@421
    88
FILE *open_file(const char *name, int decompress, int noise_mode)
slouken@0
    89
{
slouken@0
    90
  FILE *fp;
slouken@304
    91
  PathList *plp;
slouken@0
    92
  int l;
slouken@0
    93
slouken@0
    94
  if (!name || !(*name))
slouken@0
    95
    {
slouken@0
    96
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Attempted to open nameless file.");
slouken@0
    97
      return 0;
slouken@0
    98
    }
slouken@0
    99
patmandin@334
   100
  if (pathlist==NULL) {
patmandin@264
   101
    /* Generate path list */
slouken@437
   102
#ifdef DEFAULT_PATH
patmandin@264
   103
    add_to_pathlist(DEFAULT_PATH);
slouken@437
   104
#endif
slouken@437
   105
#ifdef DEFAULT_PATH1
slouken@437
   106
    add_to_pathlist(DEFAULT_PATH1);
slouken@437
   107
#endif
slouken@437
   108
#ifdef DEFAULT_PATH2
slouken@437
   109
    add_to_pathlist(DEFAULT_PATH2);
slouken@437
   110
#endif
slouken@530
   111
#ifdef DEFAULT_PATH3
slouken@530
   112
    add_to_pathlist(DEFAULT_PATH3);
slouken@530
   113
#endif
patmandin@264
   114
  }
patmandin@264
   115
slouken@0
   116
  /* First try the given name */
slouken@0
   117
icculus@449
   118
  strncpy(current_filename, name, PATH_MAX - 1);
icculus@449
   119
  current_filename[PATH_MAX - 1]='\0';
slouken@0
   120
slouken@0
   121
  ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
slouken@0
   122
  if ((fp=try_to_open(current_filename, decompress, noise_mode)))
slouken@0
   123
    return fp;
slouken@0
   124
slouken@180
   125
#ifdef ENOENT
slouken@0
   126
  if (noise_mode && (errno != ENOENT))
slouken@0
   127
    {
slouken@0
   128
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
slouken@0
   129
	   current_filename, strerror(errno));
slouken@0
   130
      return 0;
slouken@0
   131
    }
slouken@180
   132
#endif
slouken@304
   133
slouken@304
   134
  plp=pathlist;
slouken@0
   135
  if (name[0] != PATH_SEP)
slouken@0
   136
    while (plp)  /* Try along the path then */
slouken@0
   137
      {
slouken@0
   138
	*current_filename=0;
slouken@0
   139
	l=strlen(plp->path);
slouken@0
   140
	if(l)
slouken@0
   141
	  {
slouken@0
   142
	    strcpy(current_filename, plp->path);
slouken@0
   143
	    if(current_filename[l-1]!=PATH_SEP)
slouken@0
   144
	      strcat(current_filename, PATH_STRING);
slouken@0
   145
	  }
slouken@0
   146
	strcat(current_filename, name);
slouken@0
   147
	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Trying to open %s", current_filename);
slouken@0
   148
	if ((fp=try_to_open(current_filename, decompress, noise_mode)))
slouken@0
   149
	  return fp;
slouken@180
   150
#ifdef ENOENT
slouken@0
   151
	if (noise_mode && (errno != ENOENT))
slouken@0
   152
	  {
slouken@0
   153
	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", 
slouken@0
   154
		 current_filename, strerror(errno));
slouken@0
   155
	    return 0;
slouken@0
   156
	  }
slouken@180
   157
#endif
slouken@0
   158
	plp=plp->next;
slouken@0
   159
      }
slouken@0
   160
  
slouken@0
   161
  /* Nothing could be opened. */
slouken@0
   162
slouken@0
   163
  *current_filename=0;
slouken@0
   164
  
slouken@0
   165
  if (noise_mode>=2)
slouken@0
   166
    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", name, strerror(errno));
slouken@0
   167
  
slouken@0
   168
  return 0;
slouken@0
   169
}
slouken@0
   170
slouken@0
   171
/* This closes files opened with open_file */
slouken@0
   172
void close_file(FILE *fp)
slouken@0
   173
{
slouken@0
   174
#ifdef DECOMPRESSOR_LIST
slouken@0
   175
  if (pclose(fp)) /* Any better ideas? */
slouken@0
   176
#endif
slouken@0
   177
    fclose(fp);
slouken@525
   178
slouken@525
   179
  strncpy(current_filename, "MIDI file", PATH_MAX - 1);
slouken@0
   180
}
slouken@0
   181
slouken@0
   182
/* This is meant for skipping a few bytes in a file or fifo. */
slouken@0
   183
void skip(FILE *fp, size_t len)
slouken@0
   184
{
slouken@0
   185
  size_t c;
icculus@449
   186
  char tmp[PATH_MAX];
slouken@0
   187
  while (len>0)
slouken@0
   188
    {
slouken@0
   189
      c=len;
icculus@449
   190
      if (c>PATH_MAX) c=PATH_MAX;
slouken@0
   191
      len-=c;
slouken@0
   192
      if (c!=fread(tmp, 1, c, fp))
slouken@0
   193
	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: skip: %s",
slouken@0
   194
	     current_filename, strerror(errno));
slouken@0
   195
    }
slouken@0
   196
}
slouken@0
   197
slouken@0
   198
/* This'll allocate memory or die. */
slouken@0
   199
void *safe_malloc(size_t count)
slouken@0
   200
{
slouken@0
   201
  void *p;
slouken@0
   202
  if (count > (1<<21))
slouken@0
   203
    {
slouken@0
   204
      ctl->cmsg(CMSG_FATAL, VERB_NORMAL, 
slouken@0
   205
	   "Strange, I feel like allocating %d bytes. This must be a bug.",
slouken@0
   206
	   count);
slouken@0
   207
    }
slouken@0
   208
  else if ((p=malloc(count)))
slouken@0
   209
    return p;
slouken@0
   210
  else
slouken@0
   211
    ctl->cmsg(CMSG_FATAL, VERB_NORMAL, "Sorry. Couldn't malloc %d bytes.", count);
slouken@0
   212
slouken@0
   213
  ctl->close();
slouken@0
   214
  exit(10);
slouken@180
   215
  return(NULL);
slouken@0
   216
}
slouken@0
   217
slouken@0
   218
/* This adds a directory to the path list */
slouken@421
   219
void add_to_pathlist(const char *s)
slouken@0
   220
{
slouken@0
   221
  PathList *plp=safe_malloc(sizeof(PathList));
slouken@0
   222
  strcpy((plp->path=safe_malloc(strlen(s)+1)),s);
slouken@0
   223
  plp->next=pathlist;
slouken@0
   224
  pathlist=plp;
slouken@0
   225
}
patmandin@264
   226
patmandin@264
   227
/* Free memory associated to path list */
patmandin@264
   228
void free_pathlist(void)
patmandin@264
   229
{
patmandin@264
   230
  PathList *plp, *next_plp;
patmandin@264
   231
patmandin@264
   232
  plp = pathlist;
patmandin@264
   233
  while (plp) {
patmandin@264
   234
    if (plp->path) {
patmandin@264
   235
      free(plp->path);
patmandin@264
   236
      plp->path=NULL;
patmandin@264
   237
    }
patmandin@264
   238
    next_plp = plp->next;
patmandin@264
   239
    free(plp);
patmandin@264
   240
    plp = next_plp;
patmandin@264
   241
  }
patmandin@334
   242
  pathlist = NULL;
patmandin@264
   243
}