1 /*************************************************************************
2 
3                          "I Have No Tomatoes"
4                   Copyright (c) 2004, Mika Halttunen
5 
6  This software is provided 'as-is', without any express or implied
7  warranty. In no event will the authors be held liable for any damages
8  arising from the use of this software.
9 
10  Permission is granted to anyone to use this software for any purpose,
11  including commercial applications, and to alter it and redistribute
12  it freely, subject to the following restrictions:
13 
14     1. The origin of this software must not be misrepresented; you must
15     not claim that you wrote the original software. If you use this
16     software in a product, an acknowledgment in the product documentation
17     would be appreciated but is not required.
18 
19     2. Altered source versions must be plainly marked as such, and must
20     not be misrepresented as being the original software.
21 
22     3. This notice may not be removed or altered from any source
23     distribution.
24 
25 
26  Mika Halttunen <lsoft@mbnet.fi>
27 
28 *************************************************************************/
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include "SDL.h"
33 #include "SDL_mixer.h"
34 #include "game.h"
35 #include <string.h>
36 #include <dirent.h>
37 #include <ctype.h>
38 #include "mymath.h"
39 #include "init.h"
40 #include "mpak.h"
41 #include "comments.h"
42 #include "timer.h"
43 #include "soundmusic.h"
44 
45 // Current music module
46 Mix_Music *music_mod = NULL;
47 
48 // Music files array
49 char music_files[MAX_MUSIC][256];
50 int num_music_files;
51 int cur_music;
52 
53 // Sound array
54 Mix_Chunk *sounds[NUM_SOUNDS];
55 
56 
57 // Shuffle the playlist
shuffle_playlist()58 void shuffle_playlist() {
59 	if(!num_music_files)
60 		return;
61 
62 	cur_music = 0;
63 
64 	// Shuffle the list
65 	for(int i = num_music_files - 1; i > 0; i--) {
66 		int pos = RAND(0, i - 1);
67 		char swap[256];
68 		strcpy(swap, music_files[i]);
69 		strcpy(music_files[i], music_files[pos]);
70 		strcpy(music_files[pos], swap);
71 	}
72 }
73 
74 
75 // Search for the music files
search_music()76 void search_music() {
77 	DIR *dp;
78 	dirent *ep;
79 
80 	// Search files from the music directory
81 	dp = opendir(MUSIC_DIR);
82 	if(!dp || !config.sound || !config.music_vol) {
83 		// No files found, or the sound is turned off
84 		num_music_files = 0;
85 		return;
86 	}
87 
88 	// Clear music file list
89 	num_music_files = 0;
90 	cur_music = 0;
91 	for(int f=0; f<MAX_MUSIC; f++)
92 		strcpy(music_files[f], "");
93 
94 	// Start searching
95 	while((ep = readdir(dp)) ) {
96 		if(num_music_files >= MAX_MUSIC-1) {
97 			printf("Warning: Too many music files in '%s' directory!\n", MUSIC_DIR);
98 			break;
99 		}
100 
101 		// Check the extension
102 		char ext[3];
103 		char name[256] = "";
104 		strcpy(name, ep->d_name);
105 		int len = strlen(name);
106 		if(len > 3) {
107 			ext[0] = name[len-3];
108 			ext[1] = name[len-2];
109 			ext[2] = name[len-1];
110 			if(toupper(ext[0]) == 'M' && toupper(ext[1]) == 'O' && toupper(ext[2]) == 'D') {
111 				// Found MOD
112 				strcpy(music_files[num_music_files], name);
113 				num_music_files++;
114 			}
115 
116 			if(toupper(ext[0]) == 'S' && toupper(ext[1]) == '3' && toupper(ext[2]) == 'M') {
117 				// Found S3M
118 				strcpy(music_files[num_music_files], name);
119 				num_music_files++;
120 			}
121 
122 			if(toupper(ext[1]) == 'X' && toupper(ext[2]) == 'M') {
123 				// Found XM
124 				strcpy(music_files[num_music_files], name);
125 				num_music_files++;
126 			}
127 
128 			if(toupper(ext[1]) == 'I' && toupper(ext[2]) == 'T') {
129 				// Found IT
130 				strcpy(music_files[num_music_files], name);
131 				num_music_files++;
132 			}
133 
134 			if(toupper(ext[0]) == 'O' && toupper(ext[1]) == 'G' && toupper(ext[2]) == 'G') {
135 				// Found OGG
136 				strcpy(music_files[num_music_files], name);
137 				num_music_files++;
138 			}
139 		}
140 	}
141 
142 	closedir(dp);
143 	shuffle_playlist();
144 }
145 
146 
147 // If the current music has finished, start playing another
music_finished()148 void music_finished() {
149 	static bool f1_key_down = false;
150 
151 	if(!config.sound || !num_music_files || !config.music_vol)
152 		return;
153 
154 	if(f1_key_down == false) {
155 		// Play the current song from the playlist
156 		play_music(music_files[cur_music]);
157 
158 		cur_music++;
159 		if(cur_music > num_music_files-1)
160 			shuffle_playlist();
161 		f1_key_down = true;
162 	}
163 	if(!key[SDLK_F1])
164 		f1_key_down = false;
165 
166 }
167 
168 
169 // This helper function loads a sound and stores it to the sound array
170 static int cur_sound = 0;
load_sound(char * file)171 void load_sound(char *file) {
172 	if(cur_sound > NUM_SOUNDS-1)
173 		error_msg("load_sounds():\nTrying to load too many sounds!\nNUM_SOUNDS is defined as %d.\n", NUM_SOUNDS);
174 
175 	// First try to load from the override directory
176 	char soundfile[128] = "";
177 	sprintf(soundfile, "%s%s", pakfile.override_dir, file);
178 	FILE *check = fopen(soundfile, "rb");
179 	if(check) {
180 		// The file exists, load it
181 		fclose(check);
182 		sounds[cur_sound] = Mix_LoadWAV(soundfile);
183 	}
184 	else {
185 		// The file doesn't exist in the override directory
186 		// try to load it from the pakfile.
187 		FILE *fp = pakfile.open_file(file);
188 		SDL_RWops *rw = SDL_RWFromFP(fp,0);
189 		sounds[cur_sound] = Mix_LoadWAV_RW(rw,0);
190 		SDL_FreeRW(rw);
191 		fclose(fp);
192 	}
193 
194 	// Check for errors
195 	if(!sounds[cur_sound])
196 		error_msg("load_sound():\nUnable to load a sound from %s!\nError: %s\n",file,Mix_GetError());
197 	cur_sound++;
198 }
199 
200 
201 // Initialize the SDL_Mixer
init_mixer()202 void init_mixer() {
203 	if(!config.sound)
204 		return;
205 
206 	// Initialize the Mixer
207 	if(Mix_OpenAudio(config.sound_freq, AUDIO_S16, 2, 4096))	// Frequency, 16 bit sound, channels (stereo), buffer size
208 		error_msg("Unable to open the audio device!\nError: %s\n", Mix_GetError());
209 
210 	// Load the sounds
211 	load_sound("snd_appear.wav");
212 	load_sound("snd_bomb.wav");
213 	load_sound("snd_explo.wav");
214 	load_sound("snd_bonus1.wav");
215 	load_sound("snd_bonus2.wav");
216 	load_sound("snd_bonus3.wav");
217 	load_sound("snd_die1.wav");
218 	load_sound("snd_die2.wav");
219 	load_sound("snd_die3.wav");
220 	load_sound("snd_die4.wav");
221 	load_sound("snd_die5.wav");
222 	load_sound("snd_die6.wav");
223 	load_sound("snd_levelteleport.wav");
224 	load_sound("snd_wildfire.wav");
225 	load_sound("snd_teleport.wav");
226 	load_sound("snd_trap.wav");
227 	load_sound("snd_lightning.wav");
228 	load_sound("snd_wisp.wav");
229 	load_sound("snd_jump.wav");
230 	load_sound("snd_potatoman.wav");
231 	load_sound("snd_potatoman2.wav");
232 	load_sound("snd_turn.wav");
233 	load_sound("snd_flowerpower.wav");
234 	load_sound("snd_kick.wav");
235 	load_sound("snd_killed5.wav");
236 	load_sound("snd_menu1.wav");
237 	load_sound("snd_menu2.wav");
238 	load_sound("snd_finish.wav");
239 
240 	// Search for music files
241 	search_music();
242 
243 	// Set the volume
244 	Mix_Volume(-1,config.sound_vol);
245 
246 	// Start playing the music
247 	if(num_music_files) {
248 		play_music(music_files[0]);
249 		cur_music++;
250 		if(cur_music > num_music_files-1)
251 			cur_music = 0;
252 	}
253 
254 	// Tell Mixer what to do when the music stops
255 	Mix_HookMusicFinished(&music_finished);
256 }
257 
258 
259 // Play music
play_music(char * file)260 void play_music(char *file) {
261 	if(!config.sound || !config.music_vol)
262 		return;
263 
264 	game_paused = true;
265 
266 	char str[256] = "";
267 	sprintf(str, "%s%s", MUSIC_DIR, file);
268 	if(music_mod){
269 		Mix_HaltMusic();
270 		Mix_FreeMusic(music_mod);
271 	}
272 	music_mod = Mix_LoadMUS(str);
273 	if(!music_mod)
274 		error_msg("play_music():\nUnable to play music from '%s'!\nError: %s\n", file, Mix_GetError());
275 
276 	// Play
277 	Mix_PlayMusic(music_mod, 0);
278 
279 	// Add the comment
280 	add_comment(COL_DEFAULT, "Playing \"%s\"...", file);
281 
282 	// Set the volume
283 	Mix_VolumeMusic(config.music_vol);
284 
285 	game_paused = false;
286 }
287 
288 
289 // Play a sound
play_sound(int sound,bool random_freq)290 void play_sound(int sound, bool random_freq) {
291 	if(!config.sound)
292 		return;
293 
294 	// Play the sound
295 	Mix_PlayChannel(-1, sounds[sound], 0);
296 	//int channel = Mix_PlayChannel(-1, sounds[sound], 0);
297 
298 	// Random the frequency
299 	// This doesn't work in SDL!
300 /*	if(random_freq) {
301 		int freq;
302 		int freq_change[2];
303 //		freq = FSOUND_GetFrequency(channel);
304 
305 		freq_change[0] = (int)((float)freq * 0.3f);
306 		freq_change[1] = (int)((float)freq * 0.1f);
307 
308 		// Upload the frequency to the sample
309 //		FSOUND_SetFrequency(channel, freq+RAND(-freq_change[0], freq_change[1]));
310 	}
311 */
312 }
313