Crossfire Client, Branch
R11627
|
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 }