Crossfire Client, Branches  R11627
common.c
Go to the documentation of this file.
1 /*
2  * A replacement of strdup(), since it's not defined at some
3  * unix variants.
4  */
5 
6 extern int init_audio(void);
7 
8 #define MAX_SOUNDS 1024
9 char *buffers=NULL;
10 
11 void play_sound(int soundnum, int soundtype, int x, int y);
12 
13 char *strdup_local(char *str) {
14  char *c=(char *)malloc(sizeof(char)*strlen(str)+1);
15  strcpy(c,str);
16  return c;
17 }
18 
19 
20 typedef struct Sound_Info {
21  char *filename;
22  char *symbolic;
23  unsigned char volume;
24  int size;
25  unsigned char *data;
26 } Sound_Info;
27 
30 /* parses a line from the sound file. This is a little uglier because
31  * we store some static values in the function so we know what we are doing -
32  * however, it is somewhat necessary so that we can use this same function
33  * to parse both files and the compiled in data.
34  *
35  * Note that this function will modify the data in line. lineno is just
36  * for error tracking purposes.
37  */
38 
39 static void parse_sound_line(char *line, int lineno) {
40  static int readtype=0, lastnum=0;
41  int newnum, len;
42  char *cp,*volume,*symbolic,*cp1,filename[512];
43 
44  if (line[0]=='#' || line[0]=='\n') return;
45 
46  if (!strcmp(line,"Standard Sounds:\n")) {
47  lastnum=0;
48  readtype=1;
49  return;
50  }
51  if (!strcmp(line,"Spell Sounds:\n")) {
52  lastnum=0;
53  readtype=2;
54  return;
55  }
56  if (!readtype) {
57 #ifdef SOUND_DEBUG
58  fprintf(stderr,"Got input without finding section header yet:\n%d:%s\n",
59  lineno, line);
60 #endif
61  return;
62  }
63 
64  if (line[strlen(line)-1]=='\n') line[strlen(line)-1]='\0';
65 
66  len=strcspn(line, " \t");
67  line[len]='\0';
68  cp = line+len+1;
69 
70 
71  /* Skip all whitespace for the next field */
72  while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
73  cp++;
74 
75  volume=cp;
76 
77  /* No symbolic name or number - that is ok */
78  cp1=cp;
79  if (!(cp=strchr(cp1,' ')) && !(cp=strchr(cp1,'\t'))) {
80  newnum=lastnum+1;
81  symbolic=NULL;
82  } else { /* We think we have a symbolic name */
83  /* Don't need to nulterm the volume, since we atoi it anyways */
84  while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
85  cp++;
86 
87  symbolic=cp;
88  /* Some symbolc names are double quote protected. If, do some
89  * special processing. We strip off the quotes.
90  */
91  if (*symbolic=='"') {
92  symbolic++;
93  for (cp=symbolic; *cp!='\0' && *cp!='"'; cp++) ;
94  *cp='\0';
95  cp++;
96  }
97  /* Lets try to find the sound number now */
98  cp1 = cp;
99  if (!(cp=strchr(cp1,' ')) && !(cp=strchr(cp1,'\t')))
100  newnum=lastnum+1;
101  else {
102  *cp++='\0';
103  while (*cp!='\0' && (*cp==' ' || *cp=='\t'))
104  cp++;
105  if (isdigit(*cp))
106  newnum=atoi(cp);
107  else newnum=lastnum+1;
108  }
109  }
110  if (newnum < 0 || newnum>MAX_SOUNDS) {
111  fprintf(stderr,"Invalid sound number %d, line %d, buf %s\n",
112  newnum, lineno, line);
113  return;
114  }
115 
116  /* Compatibility processing for older files - if the file ends in
117  * .au, convert to .raw. A bit of a hack, but probably better than
118  * trying to play an au file.
119  */
120  strcpy(filename, line);
121  cp = filename + strlen(filename)-3;
122  if (!strcmp(cp, ".au"))
123  strcpy(cp, ".raw");
124 
125  if (symbolic && !strcmp(symbolic,"DEFAULT")) {
126  if (readtype==1) {
127  default_normal.filename=strdup_local(filename);
128  default_normal.volume=atoi(volume);
129  } else if (readtype==2) {
130  default_spell.filename=strdup_local(filename);
131  default_spell.volume=atoi(volume);
132  }
133  return;
134  }
135  else {
136  if (readtype==1) {
137  normal_sounds[newnum].filename = strdup_local(filename);
138  normal_sounds[newnum].volume = atoi(volume);
139  if (symbolic) normal_sounds[newnum].symbolic=strdup_local(symbolic);
140  else normal_sounds[newnum].symbolic=NULL;
141  } else if (readtype==2) {
142  spell_sounds[newnum].filename = strdup_local(filename);
143  spell_sounds[newnum].volume = atoi(volume);
144  if (symbolic) spell_sounds[newnum].symbolic=strdup_local(symbolic);
145  else spell_sounds[newnum].symbolic=NULL;
146  }
147  lastnum=newnum;
148  }
149 }
150 
151 /* init_sounds open the audio device, and reads any configuration files
152  * that need to be. It returns 0 on success. On failure, the calling
153  * function will likely disable sound support/requests from the server.
154  */
155 
156 int init_sounds(void)
157 {
158  int i;
159  FILE *fp;
160  char path[256], buf[512];
161 
162 #ifdef SOUND_DEBUG
163  fprintf( stderr,"Settings: bits: %i, ",settings.bit8?8:16);
164  fprintf( stderr,"%s, ",settings.sign?"signed":"unsigned");
165  fprintf( stderr,"%s, ",settings.stereo?"stereo":"mono");
166  fprintf( stderr,"frequency: %i, ",settings.frequency);
167  fprintf( stderr,"device: %s\n",settings.audiodev);
168 #endif
169 
170  buffers = (char *)malloc( settings.buffers * settings.buflen );
171  if ( !buffers ) return -1;
172  sounds_in_buffer = (int *)calloc( settings.buffers,sizeof(int) );
173  if ( !sounds_in_buffer ) return -1;
174 
175  if (init_audio()) return -1;
176 
178 
179 #ifdef SOUND_DEBUG
180  fprintf( stderr,"bits: %i, ",settings.bit8?8:16);
181  fprintf( stderr,"%s, ",sign?"signed":"unsigned");
182  fprintf( stderr,"%s, ",stereo?"stereo":"mono");
183  fprintf( stderr,"freq: %i, ",frequency);
184  fprintf( stderr,"smpl_size: %i, ",sample_size);
185  fprintf( stderr,"0level: %i\n",zerolevel);
186 #endif
187 
188  for (i=0; i<MAX_SOUNDS; i++) {
189  normal_sounds[i].filename=NULL;
190  spell_sounds[i].filename=NULL;
191  normal_sounds[i].size=-1;
192  spell_sounds[i].size=-1;
193  }
194  default_normal.filename=NULL;
195  default_spell.filename=NULL;
196 
197  sprintf(path,"%s/.crossfire/sounds", getenv("HOME"));
198  i=0;
199  if (!(fp=fopen(path,"r"))) {
200  fprintf(stderr,"Unable to open %s - will use built in defaults\n", path);
201  for (; i<sizeof(def_sounds)/sizeof(char*); i++) {
202  strcpy(buf, def_sounds[i]);
203  parse_sound_line(buf,i);
204  }
205  } else while (fgets(buf, 511, fp)!=NULL) {
206  buf[511]='\0';
207  parse_sound_line(buf, ++i);
208  }
209  /* Note in both cases below, we leave the symbolic name untouched. */
210  for (i=0; i<MAX_SOUNDS; i++) {
211  if (!normal_sounds[i].filename) {
212  normal_sounds[i].filename=default_normal.filename;
213  normal_sounds[i].volume=default_normal.volume;
214  }
215  if (!spell_sounds[i].filename) {
216  spell_sounds[i].filename=default_spell.filename;
217  spell_sounds[i].volume=default_spell.volume;
218  }
219  normal_sounds[i].data=NULL;
220  spell_sounds[i].data=NULL;
221  }
222  return 0;
223 }
224 
225 int SoundCmd(unsigned char *data, int len)
226 {
227  int x, y, num, type;
228  int i;
229 
230  i=sscanf((char *)data,"%x %x %x %x",&num,&type,&x,&y);
231  if (i!=4){
232  fprintf(stderr,"Wrong input!\n");
233  return -1;
234  }
235 #ifdef SOUND_DEBUG
236  fprintf(stderr,"Playing sound %d (type %d), offset %d, %d\n",
237  num, type, x ,y);
238 #endif
239  play_sound(num, type, x, y);
240  return 0;
241 }
242 
243 int write_settings(void) {
244 FILE *f;
245 char *home;
246 char *path;
247 
248  if ( (home=getenv("HOME")) == NULL ) return -1;
249  path=(char *)malloc(strlen(home)+strlen(CONFIG_FILE)+1);
250  if (!path) return -1;
251  strcpy(path,home);
252  strcat(path,CONFIG_FILE);
253  f=fopen(path,"w");
254  if (!f) return -1;
255  fprintf(f,"# Crossfire sound server settings\n");
256  fprintf(f,"# Please note, that not everything will work\n\n");
257  fprintf(f,"stereo: %i\n",settings.stereo);
258  fprintf(f,"bits: %i\n",settings.bit8?8:16);
259  fprintf(f,"signed: %i\n",settings.sign);
260  fprintf(f,"frequency: %i\n",settings.frequency);
261  fprintf(f,"buffers: %i\n",settings.buffers);
262  fprintf(f,"buflen: %i\n",settings.buflen);
263  fprintf(f,"simultaneously: %i\n",settings.simultaneously);
264 /* fprintf(f,"device: %s\n",settings.audiodev);*/
265  fclose(f);
266  return 0;
267 }
268 
269 int read_settings(void) {
270  FILE *f;
271  char *home;
272  char *path;
273  char linebuf[1024];
274  if ( (home=getenv("HOME")) == NULL ) return 0;
275 
276  path=(char *)malloc(strlen(home)+strlen(CONFIG_FILE)+1);
277  if (!path) return 0;
278 
279  strcpy(path,home);
280  strcat(path,CONFIG_FILE);
281 
282  f=fopen(path,"r");
283  if (!f) return -1;
284 
285  while(fgets(linebuf,1023,f)!=NULL) {
286  linebuf[1023]=0;
287  /* Strip off the newline */
288  linebuf[strlen(linebuf)-1]=0;
289 
290  if (strncmp(linebuf,"stereo:",strlen("stereo:"))==0)
291  settings.stereo=atoi(linebuf+strlen("stereo:"))?1:0;
292  else if (strncmp(linebuf,"bits:",strlen("bits:"))==0)
293  settings.bit8=(atoi(linebuf+strlen("bits:"))==8)?1:0;
294  else if (strncmp(linebuf,"signed:",strlen("signed:"))==0)
295  settings.sign=atoi(linebuf+strlen("signed:"))?1:0;
296  else if (strncmp(linebuf,"buffers:",strlen("buffers:"))==0)
297  settings.buffers=atoi(linebuf+strlen("buffers:"));
298  else if (strncmp(linebuf,"buflen:",strlen("buflen:"))==0)
299  settings.buflen=atoi(linebuf+strlen("buflen:"));
300  else if (strncmp(linebuf,"frequency:",strlen("frequency:"))==0)
301  settings.frequency=atoi(linebuf+strlen("frequency:"));
302  else if (strncmp(linebuf,"simultaneously:",strlen("simultaneously:"))==0)
303  settings.simultaneously=atoi(linebuf+strlen("simultaneously:"));
304 #if 0
305  else if (strncmp(linebuf,"device: ",strlen("device: "))==0)
306  settings.audiodev=strdup_local(linebuf+strlen("device: "));
307 #endif
308  }
309  fclose(f);
310  return 0;
311 }
Sound_Info normal_sounds[MAX_SOUNDS]
Definition: common.c:28
unsigned char volume
Definition: cfsndserv.c:122
int init_sounds(void)
Definition: common.c:156
int write_settings(void)
Definition: common.c:243
const char * audiodev
Definition: alsa9.c:105
int buffers
Definition: alsa9.c:104
char * buffers
Definition: common.c:9
int stereo
Definition: alsa9.c:101
char * filename
Definition: cfsndserv.c:120
int init_audio(void)
Definition: alsa9.c:117
int stereo
Definition: alsa9.c:104
void play_sound(int soundnum, int soundtype, int x, int y)
Definition: alsa9.c:295
char * strdup_local(char *str)
Definition: common.c:13
char * symbolic
Definition: cfsndserv.c:121
int frequency
Definition: alsa9.c:104
Sound_Info spell_sounds[MAX_SOUNDS]
Definition: common.c:28
int read_settings(void)
Definition: common.c:269
int frequency
Definition: alsa9.c:101
const char *const def_sounds[]
Definition: soundsdef.h:1
int simultaneously
Definition: alsa9.c:104
unsigned char * data
Definition: cfsndserv.c:124
int * sounds_in_buffer
Definition: alsa9.c:94
Sound_Info default_spell
Definition: common.c:28
struct Sound_Info Sound_Info
#define CONFIG_FILE
Definition: alsa9.c:88
struct sound_settings settings
int buflen
Definition: alsa9.c:104
Sound_Info default_normal
Definition: common.c:28
static void parse_sound_line(char *line, int lineno)
Definition: common.c:39
int zerolevel
Definition: alsa9.c:101
int sign
Definition: alsa9.c:101
#define MAX_SOUNDS
Definition: common.c:8
int SoundCmd(unsigned char *data, int len)
Definition: common.c:225
int sample_size
Definition: alsa9.c:101