s_main.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (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.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "s_local.h"
00027 #include "s_main.h"
00028 #include "s_music.h"
00029 #include "s_sample.h"
00030 #include "s_mix.h"
00031 
00032 #define COMPARE_VERSION(major,minor,micro) \
00033     (SDL_MIXER_MAJOR_VERSION > (major) || \
00034     (SDL_MIXER_MAJOR_VERSION == (major) && SDL_MIXER_MINOR_VERSION > (minor)) || \
00035     (SDL_MIXER_MAJOR_VERSION == (major) && SDL_MIXER_MINOR_VERSION == (minor) && \
00036      SDL_MIXER_PATCHLEVEL >= (micro)))
00037 
00038 s_env_t s_env;
00039 
00040 cvar_t *snd_volume;
00041 cvar_t *snd_distance_scale;
00042 static cvar_t *snd_init;
00043 static cvar_t *snd_rate;
00044 
00045 static void S_Restart_f(void);
00046 
00050 void S_Stop (void)
00051 {
00052     if (!s_env.initialized)
00053         return;
00054     Mix_HaltChannel(-1);
00055 
00056     memset(s_env.channels, 0, sizeof(s_env.channels));
00057 }
00058 
00062 void S_Frame (void)
00063 {
00064     if (snd_init && snd_init->modified) {
00065         S_Restart_f();
00066         snd_init->modified = qfalse;
00067     }
00068 
00069     if (!s_env.initialized)
00070         return;
00071 
00072     M_Frame();
00073 
00074     if (CL_OnBattlescape()) {
00075         int i;
00076         s_channel_t *ch;
00077         le_t *le;
00078 
00079         /* update right angle for stereo panning */
00080         AngleVectors(cl.cam.angles, NULL, s_env.right, NULL);
00081 
00082         /* update spatialization for current sounds */
00083         ch = s_env.channels;
00084 
00085         for (i = 0; i < MAX_CHANNELS; i++, ch++) {
00086             if (!ch->sample)
00087                 continue;
00088 
00089             /* reset channel's count for loop samples */
00090             ch->count = 0;
00091 
00092             S_SpatializeChannel(ch);
00093         }
00094 
00095         /* ambient sounds */
00096         le = NULL;
00097         while ((le = LE_GetNextInUse(le))) {
00098             if (le->type == ET_SOUND) {
00099                 int j;
00100                 for (j = 0; j < MAX_CHANNELS; j++) {
00101                     if (s_env.channels[j].sample == le->sample)
00102                         break;
00103                 }
00104 
00105                 if (j == MAX_CHANNELS)
00106                     S_LoopSample(le->origin, le->sample, le->volume, le->attenuation);
00107             }
00108         }
00109     }
00110 }
00111 
00115 static void S_Play_f (void)
00116 {
00117     int i;
00118 
00119     if (Cmd_Argc() < 2) {
00120         Com_Printf("Usage: %s <filename> [<filename> ...]\n", Cmd_Argv(0));
00121         return;
00122     }
00123 
00124     i = 1;
00125     while (i < Cmd_Argc()) {
00126         S_StartLocalSample(Cmd_Argv(i), SND_VOLUME_DEFAULT);
00127         i++;
00128     }
00129 }
00130 
00136 static void S_Restart_f (void)
00137 {
00138     Com_Printf("Restarting sound\n");
00139     S_Shutdown();
00140     S_Init();
00141     S_LoadSamples();
00142 }
00143 
00144 static int S_CompleteSounds (const char *partial, const char **match)
00145 {
00146     const char *filename;
00147     int matches = 0;
00148     char *localMatch[MAX_COMPLETE];
00149     size_t len = strlen(partial);
00150     const char *soundExtensions[] = SAMPLE_TYPES;
00151     const char **extension = soundExtensions;
00152     int returnValue;
00153 
00154     /* check for partial matches */
00155     while (*extension) {
00156         char pattern[MAX_OSPATH];
00157         Com_sprintf(pattern, sizeof(pattern), "sound/**.%s", *extension);
00158         FS_BuildFileList(pattern);
00159         while ((filename = FS_NextFileFromFileList(pattern)) != NULL) {
00160             char fileWithPath[MAX_OSPATH];
00161             Com_sprintf(fileWithPath, sizeof(fileWithPath), "%s", filename + 6);
00162             if (!len) {
00163                 Com_Printf("%s\n", fileWithPath);
00164             } else if (!strncmp(partial, fileWithPath, len)) {
00165                 Com_Printf("%s\n", fileWithPath);
00166                 localMatch[matches++] = strdup(fileWithPath);
00167                 if (matches >= MAX_COMPLETE)
00168                     break;
00169             }
00170         }
00171         FS_NextFileFromFileList(NULL);
00172         extension++;
00173     }
00174 
00175     returnValue = Cmd_GenericCompleteFunction(len, match, matches, (const char **)localMatch);
00176     while (--matches >= 0)
00177         free(localMatch[matches]);
00178     return returnValue;
00179 }
00180 
00185 void S_Init (void)
00186 {
00187     SDL_version version;
00188     char drivername[MAX_VAR];
00189 
00190     Com_Printf("\n------- sound initialization -------\n");
00191 
00192     memset(&s_env, 0, sizeof(s_env));
00193 
00194     snd_init = Cvar_Get("snd_init", "1", CVAR_ARCHIVE, "Should the sound renderer get initialized");
00195     snd_init->modified = qfalse; /* don't restart right away */
00196     Cmd_AddCommand("snd_restart", S_Restart_f, "Restart the sound renderer");
00197 
00198     if (!snd_init->integer) {
00199         Com_Printf("not initializing.\n");
00200         Cmd_AddCommand("music_change", Cmd_Dummy_f, "Dummy command if sound is disabled");
00201         Cvar_Get("snd_music", "PsymongN3", 0, "Background music track");
00202         return;
00203     }
00204 
00205     snd_distance_scale = Cvar_Get("snd_distance_scale", "0.1", 0, "Sound distance scale");
00206     snd_volume = Cvar_Get("snd_volume", "0.7", CVAR_ARCHIVE, "Sound volume - default is 0.7");
00207     snd_rate = Cvar_Get("snd_rate", "44100", CVAR_ARCHIVE, "Hz value for sound renderer - default is 44100");
00208     /* set volumes to be changed so they are applied again for next sound/music playing */
00210     snd_volume->modified = qtrue;
00211 
00212     Cmd_AddCommand("snd_play", S_Play_f, "Plays a sound fx file. Pass path relative to base/sound without file extension");
00213     Cmd_AddParamCompleteFunction("snd_play", S_CompleteSounds);
00214 
00215     if (SDL_WasInit(SDL_INIT_AUDIO) == 0) {
00216         if (SDL_Init(SDL_INIT_AUDIO) < 0) {
00217             Com_Printf("S_Init: %s.\n", SDL_GetError());
00218             return;
00219         }
00220     }
00221 
00222     MIX_VERSION(&version)
00223     Com_Printf("SDL_mixer version: %d.%d.%d\n", version.major, version.minor, version.patch);
00224     Com_Printf("... requested audio rate: %i\n", snd_rate->integer);
00225 
00226     if (Mix_OpenAudio(snd_rate->integer, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) == -1) {
00227         Com_Printf("S_Init: %s\n", Mix_GetError());
00228         return;
00229     }
00230 
00231     if (Mix_QuerySpec(&s_env.rate, &s_env.format, &s_env.numChannels) == 0) {
00232         Com_Printf("S_Init: %s\n", Mix_GetError());
00233         return;
00234     }
00235 
00236     if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
00237         Q_strncpyz(drivername, "(UNKNOWN)", sizeof(drivername));
00238     Com_Printf("... driver: '%s'\n", drivername);
00239 
00240     if (Mix_AllocateChannels(MAX_CHANNELS) != MAX_CHANNELS) {
00241         Com_Printf("S_Init: %s\n", Mix_GetError());
00242         return;
00243     }
00244 
00245     Mix_ChannelFinished(S_FreeChannel);
00246 
00247     Com_Printf("... audio rate: %i\n", s_env.rate);
00248     Com_Printf("... audio channels: %i\n", s_env.numChannels);
00249 
00250 #if COMPARE_VERSION(1, 2, 10)
00251     if (!(Mix_Init(MIX_INIT_OGG) & MIX_INIT_OGG))
00252         Com_Printf("... could not load ogg vorbis support\n");
00253     else
00254         Com_Printf("... loaded ogg vorbis support\n");
00255 #endif
00256 
00257     s_env.initialized = qtrue;
00258 
00259     M_Init();
00260 }
00261 
00266 void S_Shutdown (void)
00267 {
00268     if (!s_env.initialized)
00269         return;
00270 
00271     M_Shutdown();
00272 
00273     S_Stop();
00274 
00275     Mix_AllocateChannels(0);
00276 
00277     S_FreeSamples();
00278 
00279     Mix_CloseAudio();
00280 
00281     if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_AUDIO)
00282         SDL_Quit();
00283     else
00284         SDL_QuitSubSystem(SDL_INIT_AUDIO);
00285 
00286     Mem_FreeTag(cl_soundSysPool, 0);
00287 
00288     Cmd_RemoveCommand("snd_play");
00289     Cmd_RemoveCommand("snd_restart");
00290 
00291 #if COMPARE_VERSION(1, 2, 10)
00292     Mix_Quit();
00293 #endif
00294 
00295     s_env.initialized = qfalse;
00296 }

Generated by  doxygen 1.6.2