|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 static char *sound_background; 00035 static uint8 sound_map_background_disabled = 0; 00037 static sound_data_struct *sound_data; 00039 static size_t sound_data_num; 00041 static uint8 enabled = 0; 00042 00043 #ifdef HAVE_SDL_MIXER 00044 00050 static int sound_compare(const void *a, const void *b) 00051 { 00052 return strcmp(((sound_data_struct *) a)->filename, ((sound_data_struct *) b)->filename); 00053 } 00054 00057 static void sound_sort() 00058 { 00059 qsort((void *) sound_data, sound_data_num, sizeof(sound_data_struct), (void *) (int (*)()) sound_compare); 00060 } 00061 00066 static sound_data_struct *sound_find(const char *filename) 00067 { 00068 sound_data_struct key; 00069 00070 key.filename = (char *) filename; 00071 return (sound_data_struct *) bsearch((void *) &key, (void *) sound_data, sound_data_num, sizeof(sound_data_struct), sound_compare); 00072 } 00073 00080 static sound_data_struct *sound_new(int type, const char *filename, void *data) 00081 { 00082 sound_data_num++; 00083 sound_data = realloc(sound_data, sizeof(sound_data_struct) * sound_data_num); 00084 sound_data[sound_data_num - 1].type = type; 00085 sound_data[sound_data_num - 1].filename = strdup(filename); 00086 sound_data[sound_data_num - 1].data = data; 00087 00088 return &sound_data[sound_data_num - 1]; 00089 } 00090 00091 #endif 00092 00096 static void sound_free(sound_data_struct *tmp) 00097 { 00098 switch (tmp->type) 00099 { 00100 case SOUND_TYPE_CHUNK: 00101 #ifdef HAVE_SDL_MIXER 00102 Mix_FreeChunk((Mix_Chunk *) tmp->data); 00103 #endif 00104 break; 00105 00106 case SOUND_TYPE_MUSIC: 00107 #ifdef HAVE_SDL_MIXER 00108 Mix_FreeMusic((Mix_Music *) tmp->data); 00109 #endif 00110 break; 00111 00112 default: 00113 LOG(llevBug, "sound_free(): Trying to free sound with unknown type: %d.\n", tmp->type); 00114 return; 00115 } 00116 00117 free(tmp->filename); 00118 } 00119 00122 void sound_init() 00123 { 00124 sound_background = NULL; 00125 sound_data = NULL; 00126 sound_data_num = 0; 00127 enabled = 1; 00128 00129 #ifdef HAVE_SDL_MIXER 00130 if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16, MIX_DEFAULT_CHANNELS, 1024) < 0) 00131 { 00132 draw_info_format(COLOR_RED, "Could not initialize audio device; sound will not be heard. Reason: %s", Mix_GetError()); 00133 enabled = 0; 00134 } 00135 #else 00136 enabled =0; 00137 #endif 00138 } 00139 00142 void sound_deinit() 00143 { 00144 size_t i; 00145 00146 for (i = 0; i < sound_data_num; i++) 00147 { 00148 sound_free(&sound_data[i]); 00149 } 00150 00151 free(sound_data); 00152 sound_data = NULL; 00153 sound_data_num = 0; 00154 #ifdef HAVE_SDL_MIXER 00155 Mix_CloseAudio(); 00156 #endif 00157 enabled = 0; 00158 } 00159 00165 static void sound_add_effect(const char *filename, int volume, int loop) 00166 { 00167 #ifdef HAVE_SDL_MIXER 00168 int channel; 00169 sound_data_struct *tmp; 00170 Mix_Chunk *chunk = NULL; 00171 00172 if (!enabled) 00173 { 00174 return; 00175 } 00176 00177 /* Try to find the sound first. */ 00178 tmp = sound_find(filename); 00179 00180 if (!tmp) 00181 { 00182 chunk = Mix_LoadWAV(filename); 00183 00184 if (!chunk) 00185 { 00186 LOG(llevBug, "sound_add_effect(): Could not load '%s'. Reason: %s.\n", filename, Mix_GetError()); 00187 return; 00188 } 00189 00190 /* We loaded it now, so add it to the array of loaded sounds. */ 00191 tmp = sound_new(SOUND_TYPE_CHUNK, filename, chunk); 00192 } 00193 00194 channel = Mix_PlayChannel(-1, (Mix_Chunk *) tmp->data, loop); 00195 00196 if (channel == -1) 00197 { 00198 return; 00199 } 00200 00201 Mix_Volume(channel, (int) ((setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_SOUND) / 100.0) * ((double) volume * (MIX_MAX_VOLUME / 100.0)))); 00202 00203 /* Re-sort the array as needed. */ 00204 if (chunk) 00205 { 00206 sound_sort(); 00207 } 00208 #else 00209 (void) filename; 00210 (void) volume; 00211 (void) loop; 00212 #endif 00213 } 00214 00219 void sound_play_effect(const char *filename, int volume) 00220 { 00221 char path[HUGE_BUF]; 00222 00223 snprintf(path, sizeof(path), DIRECTORY_SFX"/%s", filename); 00224 sound_add_effect(file_path(path, "r"), volume, 0); 00225 } 00226 00232 void sound_start_bg_music(const char *filename, int volume, int loop) 00233 { 00234 #ifdef HAVE_SDL_MIXER 00235 char path[HUGE_BUF]; 00236 sound_data_struct *tmp; 00237 Mix_Music *music = NULL; 00238 00239 if (!enabled) 00240 { 00241 return; 00242 } 00243 00244 if (!strcmp(filename, "no_music") || !strcmp(filename, "Disable music")) 00245 { 00246 sound_stop_bg_music(); 00247 return; 00248 } 00249 00250 snprintf(path, sizeof(path), DIRECTORY_MEDIA"/%s", filename); 00251 00252 /* Same background music, nothing to do. */ 00253 if (sound_background && !strcmp(sound_background, path)) 00254 { 00255 return; 00256 } 00257 00258 /* Try to find the music. */ 00259 tmp = sound_find(path); 00260 00261 if (!tmp) 00262 { 00263 music = Mix_LoadMUS(file_path(path, "r")); 00264 00265 if (!music) 00266 { 00267 LOG(llevBug, "sound_start_bg_music(): Could not load '%s'. Reason: %s.\n", path, Mix_GetError()); 00268 return; 00269 } 00270 00271 /* Add the loaded music to the array. */ 00272 tmp = sound_new(SOUND_TYPE_MUSIC, path, music); 00273 } 00274 00275 sound_stop_bg_music(); 00276 00277 sound_background = strdup(path); 00278 Mix_VolumeMusic(volume); 00279 Mix_PlayMusic((Mix_Music *) tmp->data, loop); 00280 00281 /* Due to a bug in SDL_mixer, some audio types (such as XM, among 00282 * others) will continue playing even when the volume has been set to 00283 * 0, which means we need to manually pause the music if volume is 0, 00284 * and unpause it in sound_update_volume(), if the volume changes. */ 00285 if (volume == 0) 00286 { 00287 Mix_PauseMusic(); 00288 } 00289 00290 /* Re-sort the array as needed. */ 00291 if (music) 00292 { 00293 sound_sort(); 00294 } 00295 #else 00296 (void) filename; 00297 (void) volume; 00298 (void) loop; 00299 #endif 00300 } 00301 00304 void sound_stop_bg_music() 00305 { 00306 if (!enabled) 00307 { 00308 return; 00309 } 00310 00311 if (sound_background) 00312 { 00313 #ifdef HAVE_SDL_MIXER 00314 Mix_HaltMusic(); 00315 #endif 00316 free(sound_background); 00317 sound_background = NULL; 00318 } 00319 } 00320 00324 void update_map_bg_music(const char *bg_music) 00325 { 00326 if (sound_map_background_disabled) 00327 { 00328 return; 00329 } 00330 00331 if (!strcmp(bg_music, "no_music")) 00332 { 00333 sound_stop_bg_music(); 00334 } 00335 else 00336 { 00337 int loop = -1, vol = 0; 00338 char filename[MAX_BUF]; 00339 00340 if (sscanf(bg_music, "%s %d %d", filename, &loop, &vol) < 1) 00341 { 00342 LOG(llevBug, "parse_map_bg_music(): Bogus background music: '%s'\n", bg_music); 00343 return; 00344 } 00345 00346 sound_start_bg_music(filename, setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC) + vol, loop); 00347 } 00348 } 00349 00352 void sound_update_volume() 00353 { 00354 if (!enabled) 00355 { 00356 return; 00357 } 00358 00359 #ifdef HAVE_SDL_MIXER 00360 Mix_VolumeMusic(setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC)); 00361 00362 /* If there is any background music, due to a bug in SDL_mixer, we 00363 * may need to pause or unpause the music. */ 00364 if (sound_background) 00365 { 00366 /* If the new volume is 0, pause the music. */ 00367 if (setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC) == 0) 00368 { 00369 if (!Mix_PausedMusic()) 00370 { 00371 Mix_PauseMusic(); 00372 } 00373 } 00374 /* Non-zero and already paused, so resume the music. */ 00375 else if (Mix_PausedMusic()) 00376 { 00377 Mix_ResumeMusic(); 00378 } 00379 } 00380 #endif 00381 } 00382 00386 const char *sound_get_bg_music() 00387 { 00388 return sound_background; 00389 } 00390 00394 const char *sound_get_bg_music_basename() 00395 { 00396 const char *bg_music = sound_background; 00397 char *cp; 00398 00399 if (bg_music && (cp = strrchr(bg_music, '/'))) 00400 { 00401 bg_music = cp + 1; 00402 } 00403 00404 return bg_music; 00405 } 00406 00412 uint8 sound_map_background(int new) 00413 { 00414 if (new == -1) 00415 { 00416 return sound_map_background_disabled; 00417 } 00418 else 00419 { 00420 sound_map_background_disabled = new; 00421 return new; 00422 } 00423 } 00424 00429 void SoundCmd(uint8 *data, int len) 00430 { 00431 size_t pos = 0, i = 0; 00432 uint8 type; 00433 int loop, volume; 00434 char filename[MAX_BUF], c; 00435 00436 (void) len; 00437 filename[0] = '\0'; 00438 type = data[pos++]; 00439 00440 while ((c = (char) (data[pos++]))) 00441 { 00442 filename[i++] = c; 00443 } 00444 00445 filename[i] = '\0'; 00446 loop = data[pos++]; 00447 volume = data[pos++]; 00448 00449 if (type == CMD_SOUND_EFFECT) 00450 { 00451 sint8 x, y; 00452 int dist_volume; 00453 char path[HUGE_BUF]; 00454 00455 x = data[pos++]; 00456 y = data[pos++]; 00457 dist_volume = isqrt(POW2(0 - x) + POW2(0 - y)) - 1; 00458 00459 if (dist_volume < 0) 00460 { 00461 dist_volume = 0; 00462 } 00463 00464 dist_volume = 100 - dist_volume * (100 / MAX_SOUND_DISTANCE); 00465 snprintf(path, sizeof(path), DIRECTORY_SFX"/%s", filename); 00466 sound_add_effect(file_path(path, "r"), dist_volume + volume, loop); 00467 } 00468 else if (type == CMD_SOUND_BACKGROUND) 00469 { 00470 if (!sound_map_background_disabled) 00471 { 00472 sound_start_bg_music(filename, setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC) + volume, loop); 00473 } 00474 } 00475 else if (type == CMD_SOUND_ABSOLUTE) 00476 { 00477 sound_add_effect(filename, volume, loop); 00478 } 00479 else 00480 { 00481 LOG(llevBug, "SoundCmd(): Invalid sound type: %d\n", type); 00482 return; 00483 } 00484 } 00485 00488 void sound_pause_music() 00489 { 00490 #ifdef HAVE_SDL_MIXER 00491 Mix_PauseMusic(); 00492 #endif 00493 } 00494 00497 void sound_resume_music() 00498 { 00499 #ifdef HAVE_SDL_MIXER 00500 Mix_ResumeMusic(); 00501 #endif 00502 } 00503 00507 int sound_playing_music() 00508 { 00509 #ifdef HAVE_SDL_MIXER 00510 return Mix_PlayingMusic(); 00511 #else 00512 return 0; 00513 #endif 00514 }
1.7.4