remove matherr
[micropolis] / src / sim / w_sound.c
CommitLineData
bf4857d3
DP
1/*
2 * Portions Copyright (c) 2008 Deanna Phillips <deanna@sdf.lonestar.org>
3 */
4
6a5fa4e0
MG
5/* w_sound.c
6 *
7 * Micropolis, Unix Version. This game was released for the Unix platform
8 * in or about 1990 and has been modified for inclusion in the One Laptop
9 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
10 * you need assistance with this program, you may contact:
11 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
12 *
13 * This program is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or (at
16 * your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details. You should have received a
22 * copy of the GNU General Public License along with this program. If
23 * not, see <http://www.gnu.org/licenses/>.
24 *
25 * ADDITIONAL TERMS per GNU GPL Section 7
26 *
27 * No trademark or publicity rights are granted. This license does NOT
28 * give you any right, title or interest in the trademark SimCity or any
29 * other Electronic Arts trademark. You may not distribute any
30 * modification of this program using the trademark SimCity or claim any
31 * affliation or association with Electronic Arts Inc. or its employees.
32 *
33 * Any propagation or conveyance of this program must include this
34 * copyright notice and these terms.
35 *
36 * If you convey this program (or any modifications of it) and assume
37 * contractual liability for the program to recipients of it, you agree
38 * to indemnify Electronic Arts for any liability that those contractual
39 * assumptions impose on Electronic Arts.
40 *
41 * You may not misrepresent the origins of this program; modified
42 * versions of the program must be marked as such and not identified as
43 * the original program.
44 *
45 * This disclaimer supplements the one included in the General Public
46 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
47 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
48 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
49 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
50 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
51 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
52 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
53 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
54 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
55 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
56 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
57 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
58 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
59 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
60 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
61 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
62 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
63 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
64 * NOT APPLY TO YOU.
65 */
6c2a3238 66#ifdef WITH_SDL_MIXER
0a295df9
DP
67#include "SDL.h"
68#include "SDL_mixer.h"
6c2a3238
MG
69#endif
70
6a5fa4e0
MG
71#include "sim.h"
72
73
bf4857d3
DP
74#define SIM_NSOUNDS 47
75#define SIM_NCHANNELS 32
76#define DOZER_CHANNEL 0
77#define DOZER_SOUND "rumble.wav"
78
79struct sound {
80 char *id;
81 char *file;
6c2a3238 82#ifdef WITH_SDL_MIXER
bf4857d3 83 Mix_Chunk *wave;
6c2a3238
MG
84#else
85 void *wave;
86#endif
bf4857d3
DP
87};
88
89struct sound sounds[SIM_NSOUNDS] = {
90 { "A", "a.wav", NULL },
91 { "Aaah", "aaah.wav", NULL },
92 { "Airport", "airport.wav", NULL },
93 { "Beep", "beep.wav", NULL },
94 { "Boing", "boing.wav", NULL },
95 { "Bop", "bop.wav", NULL },
96 { "Build", "build.wav", NULL },
97 { "Bulldozer", "bulldozer.wav", NULL },
98 { "Chalk", "chalk.wav", NULL },
99 { "Coal", "coal.wav", NULL },
100 { "Com", "com.wav", NULL },
101 { "Computer", "computer.wav", NULL },
102 { "Cuckoo", "cuckoo.wav", NULL },
103 { "E", "e.wav", NULL },
104 { "Eraser", "eraser.wav", NULL },
105 { "Explosion-High", "explosion-high.wav", NULL },
106 { "Explosion-Low", "explosion-low.wav", NULL },
107 { "Fire", "fire.wav", NULL },
108 { "HeavyTraffic", "heavytraffic.wav", NULL },
109 { "HonkHonk-High", "honkhonk-high.wav", NULL },
110 { "HonkHonk-Low", "honkhonk-low.wav", NULL },
111 { "HonkHonk-Med", "honkhonk-med.wav", NULL },
112 { "Ignition", "ignition.wav", NULL },
113 { "Ind", "ind.wav", NULL },
114 { "Monster", "monster.wav", NULL },
115 { "Nuclear", "nuclear.wav", NULL },
116 { "O", "o.wav", NULL },
117 { "Oop", "oop.wav", NULL },
118 { "Park", "park.wav", NULL },
119 { "Player", "player.wav", NULL },
120 { "Police", "police.wav", NULL },
121 { "QuackQuack", "quackquack.wav", NULL },
122 { "Query", "query.wav", NULL },
123 { "Rail", "rail.wav", NULL },
124 { "Res", "res.wav", NULL },
125 { "Road", "road.wav", NULL },
126 { "Rumble", "rumble.wav", NULL },
127 { "Seaport", "seaport.wav", NULL },
128 { "Siren", "siren.wav", NULL },
129 { "Skid", "skid.wav", NULL },
130 { "Sorry", "sorry.wav", NULL },
131 { "Stadium", "stadium.wav", NULL },
132 { "UhUh", "uhuh.wav", NULL },
133 { "Whip", "whip.wav", NULL },
134 { "Wire", "wire.wav", NULL },
135 { "Woosh", "woosh.wav", NULL },
136 { "Zone", "zone.wav", NULL }
137};
138
6c2a3238
MG
139static int SoundInitialized = 0;
140
141#ifdef WITH_SDL_MIXER
6a5fa4e0
MG
142/* Sound routines */
143
144
bf4857d3 145Mix_Chunk *rumble;
6a5fa4e0
MG
146
147
6f214ac0
MG
148void
149InitializeSound(void)
6a5fa4e0 150{
bf4857d3
DP
151 int reserved_chans;
152 char buf[256];
6a5fa4e0 153
bf4857d3
DP
154 if (SDL_Init(SDL_INIT_AUDIO) == -1) {
155 fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
156 return;
157 }
6a5fa4e0 158
bf4857d3
DP
159 if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 1, 1024) == -1) {
160 fprintf(stderr, "Mix_OpenAudio: %s\n", Mix_GetError());
161 return;
162 }
163
164 reserved_chans = Mix_ReserveChannels(1);
6a5fa4e0 165
bf4857d3
DP
166 if (reserved_chans != 1) {
167 fprintf(stderr, "Mix_ReserveChannels: %s\n", Mix_GetError());
168 return;
169 }
170
171 if (Mix_AllocateChannels(SIM_NCHANNELS) == -1) {
172 fprintf(stderr, "Mix_AllocateChannels: %s\n", Mix_GetError());
173 return;
174 }
175
176 snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir, DOZER_SOUND);
177 rumble = Mix_LoadWAV(buf);
178
179 if (rumble == NULL) {
180 printf("Mix_LoadWAV: %s\n", Mix_GetError());
181 return;
182 }
183
184 SoundInitialized = 1;
6a5fa4e0
MG
185}
186
187
6f214ac0 188void
6a5fa4e0
MG
189ShutDownSound()
190{
bf4857d3
DP
191 int i;
192 SoundInitialized = 0;
193
194 for (i = 0; i < SIM_NSOUNDS; i++) {
195 if (sounds[i].wave) {
196 Mix_FreeChunk(sounds[i].wave);
197 sounds[i].wave = NULL;
198 }
199 }
200 if (rumble) {
201 Mix_FreeChunk(rumble);
202 rumble = NULL;
6a5fa4e0 203 }
bf4857d3
DP
204 Mix_CloseAudio();
205 SDL_Quit();
6a5fa4e0
MG
206}
207
208
6f214ac0 209void
6a5fa4e0
MG
210MakeSound(char *channel, char *id)
211{
212 char buf[256];
bf4857d3 213 int i;
6a5fa4e0
MG
214
215 if (!UserSoundOn) return;
bf4857d3 216 if (!SoundInitialized) return;
6a5fa4e0 217
bf4857d3
DP
218 for (i = 0; i < SIM_NSOUNDS; i++) {
219 if (!strcmp(sounds[i].id, id))
220 break;
221 }
222
223 if (sounds[i].wave) {
224 if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1)
225 fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
226 return;
227 }
228
229 snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir,
230 sounds[i].file);
231
232 sounds[i].wave = Mix_LoadWAV(buf);
6a5fa4e0 233
bf4857d3
DP
234 if (sounds[i].wave == NULL) {
235 fprintf(stderr, "Mix_LoadWAV: %s\n", Mix_GetError());
236 return;
237 }
238
239 if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1)
240 fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
241}
6a5fa4e0 242
6f214ac0 243void
6a5fa4e0
MG
244StartBulldozer(void)
245{
246 if (!UserSoundOn) return;
bf4857d3
DP
247 if (!SoundInitialized) return;
248
249 if (Mix_PlayChannel(DOZER_CHANNEL, rumble, 4) == -1) {
250 printf("Mix_PlayChannel: %s\n", Mix_GetError());
251 return;
6a5fa4e0
MG
252 }
253}
254
255
6f214ac0 256void
6a5fa4e0
MG
257StopBulldozer(void)
258{
bf4857d3
DP
259 if (!UserSoundOn) return;
260 if (!SoundInitialized) return;
261
262 Mix_HaltChannel(DOZER_CHANNEL);
6a5fa4e0
MG
263}
264
6c2a3238 265#else /* WITH_SDL_MIXER */
6f214ac0 266void
6c2a3238
MG
267InitializeSound()
268{
c926d330 269 SoundInitialized = 1;
6c2a3238
MG
270}
271
6f214ac0 272void
6c2a3238
MG
273ShutDownSound()
274{
c926d330 275 SoundInitialized = 0;
6c2a3238
MG
276}
277
6f214ac0 278void
6c2a3238
MG
279MakeSound(char *channel, char *id)
280{
c926d330 281 char filename[256], player[256];
8dc79b2c
MG
282 static struct timeval last = {0, 0};
283 struct timeval now;
284 unsigned int diff;
c926d330
MG
285 int i;
286 pid_t pid;
6c2a3238 287
8dc79b2c
MG
288 gettimeofday(&now, NULL);
289
290 diff = ((now.tv_sec - last.tv_sec) * 1000000) +
291 (now.tv_usec - last.tv_usec);
292
293 if (diff < 100000)
294 return;
295
296 last = now;
297
c926d330
MG
298 if (!UserSoundOn) return;
299 if (!SoundInitialized) return;
300
301 for (i = 0; i < SIM_NSOUNDS; i++) {
302 if (!strcmp(sounds[i].id, id))
303 break;
304 }
305
306 snprintf(filename, sizeof(filename), "%s/sounds/%s", ResourceDir,
307 sounds[i].file);
308
309 snprintf(player, sizeof(player), "%s/sounds/player", ResourceDir);
310
311 pid = fork();
312
313 switch(pid) {
314 case 0:
315 execl(player, player, filename, NULL);
147021e0 316 exit(1);
c926d330
MG
317 break;
318 case -1:
319 perror("fork failed");
320 break;
321 default:
322 break;
323 }
6c2a3238
MG
324}
325
6f214ac0 326void
6c2a3238
MG
327StartBulldozer(void)
328{
c926d330 329 MakeSound(0, "Rumble");
6c2a3238
MG
330}
331
6f214ac0 332void
6c2a3238
MG
333StopBulldozer(void)
334{
335}
336#endif
337
6a5fa4e0 338
6f214ac0 339void
c926d330
MG
340MakeSoundOn(SimView *view, char *channel, char *id)
341{
342 if (!UserSoundOn) return;
343 if (!SoundInitialized) return;
344
345 MakeSound(channel, id);
346}
347
348
bf4857d3 349/* XXX comefrom: doKeyEvent */
6f214ac0 350void
6a5fa4e0
MG
351SoundOff(void)
352{
bf4857d3 353 ShutDownSound();
6a5fa4e0
MG
354}
355
356
6f214ac0 357void
6a5fa4e0
MG
358DoStartSound(char *channel, char *id)
359{
bf4857d3
DP
360 MakeSound(channel, id);
361}
6a5fa4e0 362
6f214ac0 363void
bf4857d3
DP
364DoStopSound(char *id)
365{
366 StopBulldozer();
6a5fa4e0
MG
367}
368
6f214ac0 369int
bf4857d3
DP
370SoundCmd(CLIENT_ARGS)
371{
372 if (!strcmp(argv[2], "Rumble"))
373 StartBulldozer();
374 else
375 MakeSound(NULL, argv[2]);
376 return 0;
377}
6a5fa4e0 378
6f214ac0 379int
bf4857d3 380DozerCmd(CLIENT_ARGS)
6a5fa4e0 381{
bf4857d3
DP
382 StopBulldozer();
383 return 0;
384}
6a5fa4e0 385
6f214ac0
MG
386void
387sound_command_init(void)
bf4857d3
DP
388{
389 Tcl_CreateCommand(tk_mainInterp, "playsound", SoundCmd,
390 (ClientData)NULL, (void (*)()) NULL);
391 Tcl_CreateCommand(tk_mainInterp, "stopdozer", DozerCmd,
392 (ClientData)NULL, (void (*)()) NULL);
6a5fa4e0 393}
Impressum, Datenschutz