- music patch from MatzeB, should fix crash on level exit too worldmap
[supertux.git] / src / sound.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //  Copyright (C) 2004 Duong-Khang NGUYEN <neoneurone@users.sf.net>
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 #include "defines.h"
22 #include "globals.h"
23 #include "sound.h"
24 #include "setup.h"
25
26 /*global variable*/
27 bool use_sound;           /* handle sound on/off menu and command-line option */
28 bool use_music;           /* handle music on/off menu and command-line option */
29 bool audio_device;        /* != 0: available and initialized */
30 int current_music;
31
32 char * soundfilenames[NUM_SOUNDS] = {
33                                        "/sounds/jump.wav",
34                                        "/sounds/bigjump.wav",
35                                        "/sounds/skid.wav",
36                                        "/sounds/distro.wav",
37                                        "/sounds/herring.wav",
38                                        "/sounds/brick.wav",
39                                        "/sounds/hurt.wav",
40                                        "/sounds/squish.wav",
41                                        "/sounds/fall.wav",
42                                        "/sounds/ricochet.wav",
43                                        "/sounds/bump-upgrade.wav",
44                                        "/sounds/upgrade.wav",
45                                        "/sounds/excellent.wav",
46                                        "/sounds/coffee.wav",
47                                        "/sounds/shoot.wav",
48                                        "/sounds/lifeup.wav",
49                                        "/sounds/stomp.wav",
50                                        "/sounds/kick.wav"
51                                     };
52
53
54 #include <SDL_mixer.h>
55
56 Mix_Chunk * sounds[NUM_SOUNDS];
57 Mix_Music * herring_song = 0;
58 Mix_Music * current_song = 0;
59
60 /* --- OPEN THE AUDIO DEVICE --- */
61
62 int open_audio (int frequency, Uint16 format, int channels, int chunksize)
63 {
64   /* if success we reserved some channels and register panning effects */
65   if (Mix_OpenAudio( frequency, format, channels, chunksize ) == 0)
66     {
67       if (Mix_ReserveChannels( SOUND_RESERVED_CHANNELS )
68                             != SOUND_RESERVED_CHANNELS )
69         {
70           DEBUG_MSG( "Warning: open_audio could'nt reserve channels" );
71         }
72
73       /* prepare the spanning effects, no error checking */
74       Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
75       Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
76       return 0;
77     }
78   else
79     {
80       return -1;
81     }
82 }
83
84
85 /* --- CLOSE THE AUDIO DEVICE --- */
86
87 void close_audio( void )
88 {
89   if (audio_device) {
90     Mix_UnregisterAllEffects( SOUND_LEFT_SPEAKER );
91     Mix_UnregisterAllEffects( SOUND_RIGHT_SPEAKER );
92     Mix_CloseAudio();
93   }
94 }
95
96
97 /* --- LOAD A SOUND --- */
98
99 Mix_Chunk * load_sound(const std::string& file)
100 {
101   Mix_Chunk * snd;
102
103   snd = Mix_LoadWAV(file.c_str());
104
105   /* printf message and abort if there is an initialized audio device */
106   if ((snd == NULL) && audio_device)
107     st_abort("Can't load", file);
108
109   return(snd);
110 }
111
112
113 /* --- LOAD A SONG --- */
114
115 Mix_Music * load_song(const std::string& file)
116 {
117   if(!audio_device)
118     return 0;
119   
120   Mix_Music * sng;
121
122   sng = Mix_LoadMUS(file.c_str());
123
124   /* printf message and abort if there is an initialized audio device */
125   if (sng == NULL)
126     st_abort("Can't load", file);
127  
128   return (sng);
129 }
130
131
132 /* --- PLAY A SOUND ON LEFT OR RIGHT OR CENTER SPEAKER --- */
133
134 void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker)
135 {
136   /* this won't call the function if the user has disabled sound
137    * either via menu or via command-line option
138    */
139   if (use_sound && audio_device)
140     {
141       Mix_PlayChannel( whichSpeaker, snd, 0);
142
143       /* prepare for panning effects for next call */
144       /* warning: currently, I do not check for errors here */
145       switch (whichSpeaker) {
146         case SOUND_LEFT_SPEAKER:
147           Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 );
148           break;
149         case SOUND_RIGHT_SPEAKER:
150           Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 );
151           break;
152         default:  // keep the compiler happy
153           break;
154       }
155     }
156 }
157
158
159 void free_chunk(Mix_Chunk *chunk)
160 {
161   if (chunk != NULL)
162     {
163       DEBUG_MSG( __PRETTY_FUNCTION__ );
164       Mix_FreeChunk( chunk );
165       chunk = NULL;
166     }
167 }
168
169 void halt_music(void)
170 {
171   if (!use_music || !audio_device)
172     return;
173
174   Mix_HaltMusic();
175   current_song = 0;
176 }
177
178
179 void play_music(Mix_Music *music)
180 {
181   if (!audio_device)
182     return;
183
184   if (use_music && Mix_PlayMusic(music, -1) < 0)
185     st_abort("Couldn't play music: ", Mix_GetError());
186
187   current_song = music;
188 }
189
190
191 void free_music(Mix_Music *music)
192 {
193   Mix_FreeMusic( music );
194 }
195
196 void enable_music(bool enable)
197 {
198   if(!audio_device)
199     return;
200   
201   use_music = enable;
202   if(!use_music)
203     Mix_HaltMusic();
204   else
205     Mix_PlayMusic(current_song, -1);
206 }
207