Crossfire Client, Branch  R11627
common.c
Go to the documentation of this file.
00001 /*
00002  * A replacement of strdup(), since it's not defined at some
00003  * unix variants.
00004  */
00005 
00006 extern int init_audio(void);
00007 
00008 #define MAX_SOUNDS 1024
00009 char *buffers=NULL;
00010 
00011 void play_sound(int soundnum, int soundtype, int x, int y);
00012 
00013 char *strdup_local(char *str) {
00014   char *c=(char *)malloc(sizeof(char)*strlen(str)+1);
00015   strcpy(c,str);
00016   return c;
00017 }
00018 
00019 
00020 typedef struct Sound_Info {
00021     char *filename;
00022     char *symbolic;
00023     unsigned char volume;
00024     int size;
00025     unsigned char *data;
00026 } Sound_Info;
00027 
00028 Sound_Info normal_sounds[MAX_SOUNDS], spell_sounds[MAX_SOUNDS],
00029 default_normal, default_spell;
00030 /* parses a line from the sound file.  This is a little uglier because
00031  * we store some static values in the function so we know what we are doing -
00032  * however, it is somewhat necessary so that we can use this same function
00033  * to parse both files and the compiled in data.
00034  *
00035  * Note that this function will modify the data in line.  lineno is just
00036  * for error tracking purposes.
00037  */
00038 
00039 static void parse_sound_line(char *line, int lineno) {
00040     static int readtype=0, lastnum=0;
00041     int newnum, len;
00042     char *cp,*volume,*symbolic,*cp1,filename[512];
00043 
00044     if (line[0]=='#' || line[0]=='\n') return;
00045 
00046     if (!strcmp(line,"Standard Sounds:\n")) {
00047         lastnum=0;
00048         readtype=1;
00049         return;
00050     }
00051     if (!strcmp(line,"Spell Sounds:\n")) {
00052         lastnum=0;
00053         readtype=2;
00054         return;
00055     }
00056     if (!readtype) {
00057 #ifdef SOUND_DEBUG
00058         fprintf(stderr,"Got input without finding section header yet:\n%d:%s\n",
00059                 lineno, line);
00060 #endif
00061         return;
00062     }
00063 
00064     if (line[strlen(line)-1]=='\n') line[strlen(line)-1]='\0';
00065 
00066     len=strcspn(line, " \t");
00067     line[len]='\0';
00068     cp = line+len+1;
00069 
00070 
00071     /* Skip all whitespace for the next field */
00072     while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
00073         cp++;
00074 
00075     volume=cp;
00076 
00077     /* No symbolic name or number - that is ok */
00078     cp1=cp;
00079     if (!(cp=strchr(cp1,' ')) && !(cp=strchr(cp1,'\t'))) {
00080         newnum=lastnum+1;
00081         symbolic=NULL;
00082     } else {    /* We think we have a symbolic name */
00083         /* Don't need to nulterm the volume, since we atoi it anyways */
00084         while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
00085             cp++;
00086 
00087         symbolic=cp;
00088         /* Some symbolc names are double quote protected.  If, do some
00089          * special processing.  We strip off the quotes.
00090          */
00091         if (*symbolic=='"') {
00092             symbolic++;
00093             for (cp=symbolic; *cp!='\0' && *cp!='"'; cp++) ;
00094             *cp='\0';
00095             cp++;
00096         }
00097         /* Lets try to find the sound number now */
00098         cp1 = cp;
00099         if (!(cp=strchr(cp1,' '))  && !(cp=strchr(cp1,'\t')))
00100             newnum=lastnum+1;
00101         else {
00102             *cp++='\0';
00103             while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
00104                 cp++;
00105             if (isdigit(*cp))
00106                 newnum=atoi(cp);
00107             else newnum=lastnum+1;
00108         }
00109     }
00110     if (newnum < 0 || newnum>MAX_SOUNDS) {
00111         fprintf(stderr,"Invalid sound number %d, line %d, buf %s\n",
00112                 newnum, lineno, line);
00113         return;
00114     }
00115 
00116     /* Compatibility processing for older files - if the file ends in
00117      * .au, convert to .raw.  A bit of a hack, but probably better than
00118      * trying to play an au file.
00119      */
00120     strcpy(filename, line);
00121     cp = filename + strlen(filename)-3;
00122     if (!strcmp(cp, ".au"))
00123         strcpy(cp, ".raw");
00124 
00125     if (symbolic && !strcmp(symbolic,"DEFAULT")) {
00126         if (readtype==1) {
00127             default_normal.filename=strdup_local(filename);
00128             default_normal.volume=atoi(volume);
00129         } else if (readtype==2) {
00130             default_spell.filename=strdup_local(filename);
00131             default_spell.volume=atoi(volume);
00132         }
00133         return;
00134     }
00135     else {
00136         if (readtype==1) {
00137             normal_sounds[newnum].filename = strdup_local(filename);
00138             normal_sounds[newnum].volume = atoi(volume);
00139             if (symbolic) normal_sounds[newnum].symbolic=strdup_local(symbolic);
00140             else normal_sounds[newnum].symbolic=NULL;
00141         } else if (readtype==2) {
00142             spell_sounds[newnum].filename = strdup_local(filename);
00143             spell_sounds[newnum].volume = atoi(volume);
00144             if (symbolic) spell_sounds[newnum].symbolic=strdup_local(symbolic);
00145             else spell_sounds[newnum].symbolic=NULL;
00146         }
00147         lastnum=newnum;
00148     }
00149 }
00150 
00151 /* init_sounds open the audio device, and reads any configuration files
00152  * that need to be.  It returns 0 on success.  On failure, the calling
00153  * function will likely disable sound support/requests from the server.
00154  */
00155 
00156 int init_sounds(void)
00157 {
00158     int i;
00159     FILE *fp;
00160     char path[256], buf[512];
00161 
00162 #ifdef SOUND_DEBUG
00163     fprintf( stderr,"Settings: bits: %i, ",settings.bit8?8:16);
00164     fprintf( stderr,"%s, ",settings.sign?"signed":"unsigned");
00165     fprintf( stderr,"%s, ",settings.stereo?"stereo":"mono");
00166     fprintf( stderr,"frequency: %i, ",settings.frequency);
00167     fprintf( stderr,"device: %s\n",settings.audiodev);
00168 #endif
00169 
00170     buffers = (char *)malloc( settings.buffers * settings.buflen );
00171     if ( !buffers ) return -1;
00172     sounds_in_buffer = (int *)calloc( settings.buffers,sizeof(int) );
00173     if ( !sounds_in_buffer ) return -1;
00174 
00175     if (init_audio()) return -1;
00176 
00177     memset(buffers,zerolevel,settings.buflen*settings.buffers);
00178 
00179 #ifdef SOUND_DEBUG
00180     fprintf( stderr,"bits: %i, ",settings.bit8?8:16);
00181     fprintf( stderr,"%s, ",sign?"signed":"unsigned");
00182     fprintf( stderr,"%s, ",stereo?"stereo":"mono");
00183     fprintf( stderr,"freq: %i, ",frequency);
00184     fprintf( stderr,"smpl_size: %i, ",sample_size);
00185     fprintf( stderr,"0level: %i\n",zerolevel);
00186 #endif
00187 
00188     for (i=0; i<MAX_SOUNDS; i++) {
00189         normal_sounds[i].filename=NULL;
00190         spell_sounds[i].filename=NULL;
00191         normal_sounds[i].size=-1;
00192         spell_sounds[i].size=-1;
00193     }
00194     default_normal.filename=NULL;
00195     default_spell.filename=NULL;
00196 
00197     sprintf(path,"%s/.crossfire/sounds", getenv("HOME"));
00198     i=0;
00199     if (!(fp=fopen(path,"r"))) {
00200         fprintf(stderr,"Unable to open %s - will use built in defaults\n", path);
00201         for (; i<sizeof(def_sounds)/sizeof(char*); i++) {
00202             strcpy(buf, def_sounds[i]);
00203             parse_sound_line(buf,i);
00204         }
00205     } else while (fgets(buf, 511, fp)!=NULL) {
00206         buf[511]='\0';
00207         parse_sound_line(buf, ++i);
00208     }
00209     /* Note in both cases below, we leave the symbolic name untouched. */
00210     for (i=0; i<MAX_SOUNDS; i++) {
00211         if (!normal_sounds[i].filename) {
00212             normal_sounds[i].filename=default_normal.filename;
00213             normal_sounds[i].volume=default_normal.volume;
00214         }
00215         if (!spell_sounds[i].filename) {
00216             spell_sounds[i].filename=default_spell.filename;
00217             spell_sounds[i].volume=default_spell.volume;
00218         }
00219         normal_sounds[i].data=NULL;
00220         spell_sounds[i].data=NULL;
00221     }
00222     return 0;
00223 }
00224 
00225 int SoundCmd(unsigned char *data,  int len)
00226 {
00227     int x, y, num, type;
00228     int i;
00229 
00230     i=sscanf((char *)data,"%x %x %x %x",&num,&type,&x,&y);
00231     if (i!=4){
00232         fprintf(stderr,"Wrong input!\n");
00233         return -1;
00234     }
00235 #ifdef SOUND_DEBUG
00236     fprintf(stderr,"Playing sound %d (type %d), offset %d, %d\n",
00237             num, type, x ,y);
00238 #endif
00239     play_sound(num, type, x, y);
00240     return 0;
00241 }
00242 
00243 int write_settings(void) {
00244 FILE *f;
00245 char *home;
00246 char *path;
00247 
00248   if ( (home=getenv("HOME")) == NULL ) return -1;
00249   path=(char *)malloc(strlen(home)+strlen(CONFIG_FILE)+1);
00250   if (!path) return -1;
00251   strcpy(path,home);
00252   strcat(path,CONFIG_FILE);
00253   f=fopen(path,"w");
00254   if (!f) return -1;
00255   fprintf(f,"# Crossfire sound server settings\n");
00256   fprintf(f,"# Please note, that not everything will work\n\n");
00257   fprintf(f,"stereo: %i\n",settings.stereo);
00258   fprintf(f,"bits: %i\n",settings.bit8?8:16);
00259   fprintf(f,"signed: %i\n",settings.sign);
00260   fprintf(f,"frequency: %i\n",settings.frequency);
00261   fprintf(f,"buffers: %i\n",settings.buffers);
00262   fprintf(f,"buflen: %i\n",settings.buflen);
00263   fprintf(f,"simultaneously: %i\n",settings.simultaneously);
00264 /*  fprintf(f,"device: %s\n",settings.audiodev);*/
00265   fclose(f);
00266   return 0;
00267 }
00268 
00269 int read_settings(void) {
00270     FILE *f;
00271     char *home;
00272     char *path;
00273     char linebuf[1024];
00274     if ( (home=getenv("HOME")) == NULL ) return 0;
00275 
00276     path=(char *)malloc(strlen(home)+strlen(CONFIG_FILE)+1);
00277     if (!path) return 0;
00278 
00279     strcpy(path,home);
00280     strcat(path,CONFIG_FILE);
00281 
00282     f=fopen(path,"r");
00283     if (!f) return -1;
00284 
00285     while(fgets(linebuf,1023,f)!=NULL) {
00286         linebuf[1023]=0;
00287         /* Strip off the newline */
00288         linebuf[strlen(linebuf)-1]=0;
00289 
00290         if (strncmp(linebuf,"stereo:",strlen("stereo:"))==0)
00291             settings.stereo=atoi(linebuf+strlen("stereo:"))?1:0;
00292         else if (strncmp(linebuf,"bits:",strlen("bits:"))==0)
00293             settings.bit8=(atoi(linebuf+strlen("bits:"))==8)?1:0;
00294         else if (strncmp(linebuf,"signed:",strlen("signed:"))==0)
00295             settings.sign=atoi(linebuf+strlen("signed:"))?1:0;
00296         else if (strncmp(linebuf,"buffers:",strlen("buffers:"))==0)
00297             settings.buffers=atoi(linebuf+strlen("buffers:"));
00298         else if (strncmp(linebuf,"buflen:",strlen("buflen:"))==0)
00299             settings.buflen=atoi(linebuf+strlen("buflen:"));
00300         else if (strncmp(linebuf,"frequency:",strlen("frequency:"))==0)
00301             settings.frequency=atoi(linebuf+strlen("frequency:"));
00302         else if (strncmp(linebuf,"simultaneously:",strlen("simultaneously:"))==0)
00303             settings.simultaneously=atoi(linebuf+strlen("simultaneously:"));
00304 #if 0
00305         else if (strncmp(linebuf,"device: ",strlen("device: "))==0)
00306                 settings.audiodev=strdup_local(linebuf+strlen("device: "));
00307 #endif
00308     }
00309     fclose(f);
00310     return 0;
00311 }