1 /*
2  * Copyright (c) 2000 Mark B. Allan. All rights reserved.
3  *
4  * "Chromium B.S.U." is free software; you can redistribute
5  * it and/or use it and/or modify it under the terms of the
6  * "Clarified Artistic License"
7  */
8 
9 #ifdef HAVE_CONFIG_H
10 #include <chromium-bsu-config.h>
11 #endif
12 
13 #ifdef AUDIO_OPENAL
14 
15 #include "gettext.h"
16 
17 #include "AudioOpenAL.h"
18 
19 #ifdef macintosh
20 	#include <MacHeaders.h>
alcCreateContext(int)21 	void	*alcCreateContext(int) { alInit(NULL); return (void*)1; }
alcDestroyContext(void *)22 	void	alcDestroyContext(void*) { alExit(); }
23 #endif //macintosh
24 
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstdarg>
28 #include <cstring>
29 
30 #ifndef _WIN32
31 	#include <unistd.h>
32 	#include <cerrno>
33 	#include <fcntl.h>
34 	#include <sys/stat.h>
35 	#include <sys/types.h>
36 #endif //_WIN32
37 
38 #ifdef HAVE_OPENAL_AL_H
39 #include <OpenAL/al.h>
40 #elif defined(HAVE_AL_AL_H)
41 #include <AL/al.h>
42 #endif
43 
44 #ifdef HAVE_OPENAL_ALC_H
45 #include <OpenAL/alc.h>
46 #elif defined(HAVE_AL_ALC_H)
47 #include <AL/alc.h>
48 #endif
49 
50 #ifdef HAVE_ALUT_ALUT_H
51 #include <ALUT/alut.h>
52 #elif defined(HAVE_AL_ALUT_H)
53 #include <AL/alut.h>
54 #endif
55 
56 #include "Config.h"
57 
58 #include "extern.h"
59 #include "define.h"
60 #include "Global.h"
61 
62 #ifdef USE_SDL
63 #ifdef USE_SDL_CDROM
64 //try to use OpenAL alc[GS]etAudioChannel extensions in Linux...
65 #ifdef __linux__
66 #define CD_VOLUME 1
67 #ifdef OLD_OPENAL
68 	#include <AL/alkludgetypes.h>
69 #else
70 	#include <AL/alext.h>
71 #endif // OLD_OPENAL
72 #endif // __linux__
73 #endif // USE_SDL_CDROM
74 #endif // USE_SDL
75 
76 // Don't try to build the CD volume stuff if it isn't available
77 #ifndef ALC_CHAN_CD_LOKI
78 #undef CD_VOLUME
79 #endif
80 
81 #ifdef __linux__
82 #define USE_PLAYLIST 1
83 #endif
84 
85 //====================================================================
AudioOpenAL()86 AudioOpenAL::AudioOpenAL()
87 	: Audio()
88 {
89 	Config	*config = Config::instance();
90 	int i;
91 	context_id	= 0;
92 	initialized = false;
93 	explosionIndex = 0;
94 	exploPopIndex = 0;
95 	origCDvolume = 0.7;
96 
97 	//-- OpenAL extensions
98 	alAttenuationScale	= 0;
99 	alcSetAudioChannel	= 0;
100 	alcGetAudioChannel	= 0;
101 	alutLoadMP3			= 0;
102 	alutLoadVorbis		= 0;
103 
104 	soundQueue = new SoundInfo;
105 
106 	for(i = 0; i < NumSoundTypes; i++)
107 	{
108 		buffer[i]	= 0;
109 		source[i]	= 0;
110 		gain[i]		= 0;
111 		sourcePos[i][0] = 0.0;
112 		sourcePos[i][1] = 0.0;
113 		sourcePos[i][2] = 0.0;
114 		numReqThisFrame[i] = 0;
115 	}
116 
117 	for(i = 0; i < NUM_EXPLO; i++)
118 	{
119 		sourceExplosion[i]	= 0;
120 	}
121 	for(i = 0; i < NUM_EXPLO_POP; i++)
122 	{
123 		sourceExploPop[i]	= 0;
124 	}
125 
126 	// NOTE: If we can't create a valid context, config->audioEnabled() will
127 	//       be set to false.
128 	if(config->audioEnabled() == true)
129 		config->setAudio(createContext());
130 
131 	if(config->audioEnabled() == true)
132 	{
133 		initSound();
134 
135 		if(alAttenuationScale)
136 		{
137 			audioScale[0] = 3.0;
138 			audioScale[1] = 1.0;
139 			audioScale[2] = 1.0;
140 		}
141 		else
142 		{
143 			if( config->debug() ) fprintf(stderr, _("alAttenuationScale == 0. Kludge it.\n"));
144 			audioScale[0] = 0.5;
145 			audioScale[1] = 0.3;
146 			audioScale[2] = 0.3;
147 			alDistanceModel(AL_NONE);
148 		}
149 
150 		if(config->swapStereo())
151 			audioScale[0] = -audioScale[0];
152 
153 #ifdef USE_SDL_CDROM
154 		if(config->usePlayList() && !cdrom)
155 #else // !USE_SDL_CDROM
156 		if(config->usePlayList())
157 #endif // !USE_SDL_CDROM
158 			loadMusicList();
159 	}
160 	if( config->debug() ) fprintf(stderr, _("AudioOpenAL::Audio done\n"));
161 }
162 
~AudioOpenAL()163 AudioOpenAL::~AudioOpenAL()
164 {
165 	if(initialized)
166 	{
167 		Config	*config = Config::instance();
168 		if( config->debug() ) fprintf(stderr, _("stopping OpenAL..."));
169 
170 #ifdef USE_SDL_CDROM
171 		#ifdef CD_VOLUME
172 		if(cdrom && alcSetAudioChannel)
173 		{
174 			alcSetAudioChannel(ALC_CHAN_CD_LOKI, origCDvolume);
175 		}
176 		#endif //CD_VOLUME
177 
178 		if(cdrom)
179 			SDL_CDStop(cdrom);
180 #endif // USE_SDL_CDROM
181 
182 		checkError(_("AudioOpenAL::~Audio()"));
183 
184 		alDeleteSources(NUM_EXPLO_POP-1, sourceExploPop);
185 		alDeleteSources(NUM_EXPLO-1, sourceExplosion);
186 		alDeleteSources(NumSoundTypes, source);
187 		alDeleteBuffers(NumSoundTypes, buffer);
188 
189 		alcMakeContextCurrent(NULL);
190 
191 		#ifdef _WIN32
192 		if(context_id)
193 			alcDestroyContext((ALCcontext*)context_id);
194 		#else
195 		if(context_id)
196 			alcDestroyContext(context_id);
197 		#endif
198 
199 		alcCloseDevice(dev);
200 
201 		alutExit();
202 
203 		if( config->debug() ) fprintf(stderr, _("done.\n"));
204 	}
205 
206 	delete soundQueue;
207 }
208 
209 //----------------------------------------------------------
210 #ifdef _WIN32
warning(const char * msg,...)211 static void warning(const char *msg, ...)
212 {
213 	va_list ap;
214 	va_start( ap, msg );
215 	vfprintf( stderr, msg, ap );
216 	va_end( ap );
217 	fprintf( stderr, "\n");
218 }
219 #else
warning(const char *,...)220 static void warning(const char *, ...)
221 {
222 }
223 #endif
224 
225 /**
226  * create OpenAL context.
227  * @returns success
228  */
229 //----------------------------------------------------------
createContext()230 bool AudioOpenAL::createContext()
231 {
232 #ifdef _WIN32
233  	dev=alcOpenDevice((unsigned char*)"DirectSound",NULL);
234 	context_id=(void*)alcCreateContext(dev,NULL);
235 	alcMakeContextCurrent((ALCcontext*)context_id);
236 #else
237 #ifdef OLD_OPENAL
238 	context_id = alcCreateContext(NULL);
239 #else
240 	dev = alcOpenDevice( NULL );
241 	context_id = alcCreateContext(dev, NULL);
242 	alcMakeContextCurrent(context_id);
243 #endif
244 #endif
245 
246 	if(!context_id)
247 	{
248 		fprintf(stderr, _(
249 			"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
250 			"!! ATTENTION !! - one or more errors were encountered during audio check.\n"
251 			"!!                Audio will be disabled.\n"
252 			"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
253 		));
254 	}
255 	return (bool)context_id;
256 }
257 
258 /**
259  * Initialize OpenAL. The context should already have been created
260  * in createContext()
261  */
262 //----------------------------------------------------------
initSound()263 void AudioOpenAL::initSound()
264 {
265 	Config	*config = Config::instance();
266 	int i;
267 	ALfloat pos[] = { 0.0, -5.0,  25.0 };
268 
269 	if( config->debug() ) fprintf(stderr, _("AudioOpenAL::initSound() begin...\n"));
270 
271 	if( config->debug() ) {
272 		fprintf(stderr, _(
273 			"-OpenAL-----------------------------------------------------\n"
274 			"Vendor     : %s\n"
275 			"Renderer   : %s\n"
276 			"Version    : %s\n"),
277 			alGetString(AL_VENDOR), alGetString(AL_RENDERER), alGetString(AL_VERSION) );
278 		printExtensions(stderr,  (const char*)alGetString( AL_EXTENSIONS ));
279 		fprintf(stderr, _("------------------------------------------------------------\n"));
280 	}
281 
282 	alutInitWithoutContext(0, NULL);
283 
284 	checkForExtensions();
285 
286 	alListenerfv(AL_POSITION, pos);
287 
288 #if !defined(ALUT_API_MAJOR_VERSION) || ALUT_API_MAJOR_VERSION < 1
289 	alGenBuffers(NumSoundTypes, buffer);
290 #endif
291 	alGenSources(NumSoundTypes, source);
292 
293 	loadSounds();
294 
295 	for(i = 0; i < NumSoundTypes; i++)
296 	{
297 		switch(i)
298 		{
299 			case PowerUp:	gain[PowerUp]	= 0.7;	break;
300 			case ExploPop:	gain[ExploPop]	= 0.8;	break;
301 			case MusicGame:	gain[MusicGame]	= 0.7;	break;
302 			case MusicMenu:	gain[MusicMenu]	= 0.7;	break;
303 			default:
304 				gain[i] = 1.0;
305 				break;
306 		}
307 	}
308 
309 	for(i = 0; i < NumSoundTypes; i++)
310 	{
311 		warning(_("Audio.cpp - init %s"), fileNames[i]);
312 		alSourcefv( source[i], AL_POSITION, pos );
313 		alSourcei ( source[i], AL_LOOPING, AL_FALSE);
314 		alSourcei ( source[i], AL_BUFFER, buffer[i] );
315 		alSourcef ( source[i], AL_GAIN, gain[i]);
316 		checkError();
317 	}
318 
319 	//-- We want to have overlapped Explosion
320 	alGenSources(NUM_EXPLO-1, sourceExplosion);
321 	sourceExplosion[NUM_EXPLO-1] = source[Explosion];
322 	for(i = 0; i < NUM_EXPLO-1; i++)
323 	{
324 		warning(_("Audio.cpp - init explosion %d"), i);
325 		alSourcefv( sourceExplosion[i], AL_POSITION, pos );
326 		alSourcei ( sourceExplosion[i], AL_LOOPING, AL_FALSE);
327 		alSourcei ( sourceExplosion[i], AL_BUFFER, buffer[Explosion] );
328 		alSourcef ( sourceExplosion[i], AL_GAIN, gain[Explosion]*(0.7+0.3*FRAND) );
329 		checkError();
330 	}
331 
332 	//-- We want to have overlapped ExploPop
333 	alGenSources(NUM_EXPLO_POP-1, sourceExploPop);
334 	sourceExploPop[NUM_EXPLO_POP-1] = source[ExploPop];
335 	for(i = 0; i < NUM_EXPLO_POP-1; i++)
336 	{
337 		warning(_("Audio.cpp - init exploPop %d"), i);
338 		alSourcefv( sourceExploPop[i], AL_POSITION, pos );
339 		alSourcei ( sourceExploPop[i], AL_LOOPING, AL_FALSE);
340 		alSourcei ( sourceExploPop[i], AL_BUFFER, buffer[ExploPop] );
341 		alSourcef ( sourceExploPop[i], AL_GAIN, 0.0*gain[ExploPop]*(0.1+0.9*FRAND) );
342 		checkError();
343 	}
344 
345 
346 	setSoundVolume(config->volSound());
347 	setMusicVolume(config->volMusic());
348 
349 	initialized = true;
350 	warning(_("Audio.cpp - initSound complete."), i);
351 }
352 
353 //----------------------------------------------------------
checkForExtensions()354 void AudioOpenAL::checkForExtensions()
355 {
356 #ifndef _WIN32	// Win32 doesn't have any useful extensions yet, and
357 				// the alGetProcAddress prototype is different (sigh).
358 
359 	//-- check AttenuationScale extension
360 	alAttenuationScale = (void (*)(ALfloat param))
361 						alGetProcAddress("alAttenuationScale_LOKI");
362 
363 	alGetError(); // Don't care what the problem is
364 	if(alAttenuationScale != NULL)
365 		alAttenuationScale(6.0);
366 
367 	//-- check Audio Channel extension
368 	alcGetAudioChannel = (float (*)(ALuint channel))
369 						alGetProcAddress("alcGetAudioChannel_LOKI");
370 	alcSetAudioChannel = (void (*)(ALuint channel, ALfloat volume))
371 						alGetProcAddress("alcSetAudioChannel_LOKI");
372 #ifdef CD_VOLUME
373 	if(alcGetAudioChannel)
374 		origCDvolume = alcGetAudioChannel(ALC_CHAN_CD_LOKI);
375 #endif //CD_VOLUME
376 
377 	//-- check MP3 extension
378 	alutLoadMP3 = (ALboolean (*)(ALuint, ALvoid *, ALint))
379 		alGetProcAddress("alutLoadMP3_LOKI");
380 	//-- check Ogg/Vorbis extension
381 	alutLoadVorbis = (ALboolean (*)(ALuint, ALvoid *, ALint))
382 		alGetProcAddress("alutLoadVorbis_LOKI");
383 
384 #endif //_WIN32
385 }
386 
387 /**
388  * Stop OpenAL music. Also calls Audio::stopMusic()
389  */
390 //----------------------------------------------------------
stopMusic()391 void AudioOpenAL::stopMusic()
392 {
393 	Config	*config = Config::instance();
394 	if(config->audioEnabled() == true)
395 	{
396 		Audio::stopMusic();
397 		alSourceStop(source[MusicMenu]);
398 		alSourceStop(source[MusicGame]);
399 	}
400 }
401 
402 /**
403  * Pause OpenAL music. Also calls Audio::pauseMusic()
404  */
405 //----------------------------------------------------------
pauseGameMusic(bool status)406 void AudioOpenAL::pauseGameMusic(bool status)
407 {
408 	Config	*config = Config::instance();
409 	if(config->audioEnabled() == true)
410 	{
411 #ifdef USE_SDL_CDROM
412 		if(cdrom)
413 		{
414 			Audio::pauseGameMusic(status);
415 		}
416 		else
417 #endif // USE_SDL_CDROM
418 		{
419 			if(status)
420 				alSourcePause(source[MusicGame]);
421 			else
422 				alSourcePlay(source[MusicGame]);
423 		}
424 	}
425 }
426 
427 //----------------------------------------------------------
setMusicMode(SoundType mode)428 void AudioOpenAL::setMusicMode(SoundType mode)
429 {
430 	Global	*game = Global::getInstance();
431 	Config	*config = Config::instance();
432 	if( config->debug() ) fprintf(stderr, _("AudioOpenAL::setMusicMode(SoundType mode)\n"));
433 	if(config->audioEnabled() == true)
434 	{
435 		Audio::setMusicMode(mode);
436 		switch(mode)
437 		{
438 			default:
439 			case MusicGame:
440 				alSourceStop (source[MusicMenu]);
441 #ifdef USE_SDL_CDROM
442 				if(!cdrom)
443 #endif // USE_SDL_CDROM
444 				{
445 					alSourcei    (source[MusicGame], AL_LOOPING, AL_TRUE);
446 					if(!game->game_pause)
447 						alSourcePlay (source[MusicGame]);
448 				}
449 				break;
450 			case MusicMenu:
451 #ifdef USE_SDL_CDROM
452 				if(!cdrom)
453 #endif // USE_SDL_CDROM
454 				{
455 					alSourcePause(source[MusicGame]);
456 				}
457 				alSourcei    (source[MusicMenu], AL_LOOPING, AL_TRUE);
458 				alSourcePlay (source[MusicMenu]);
459 				break;
460 		}
461 	}
462 }
463 
464 /**
465  * adjust gain of OpenAL sounds
466  */
467 //----------------------------------------------------------
setSoundVolume(float vol)468 void AudioOpenAL::setSoundVolume(float vol)
469 {
470 	Config	*config = Config::instance();
471 	if( config->debug() ) fprintf(stderr, _("AudioOpenAL::setSoundVolume(%f)\n"), vol);
472 	if(config->audioEnabled() == true)
473 	{
474 		int i;
475 		if(vol > 1.0) vol = 1.0;
476 		if(vol < 0.0) vol = 0.0;
477 		soundVolume = vol;
478 		for(i = 0; i < MusicGame; i++)
479 		{
480 			alSourcef ( source[i], AL_GAIN, gain[i]*vol);
481 		}
482 		for(i = 0; i < NUM_EXPLO; i++)
483 		{
484 			alSourcef ( sourceExplosion[i], AL_GAIN, (0.5+(FRAND*0.5))*gain[Explosion]*soundVolume);
485 		}
486 		for(i = 0; i < NUM_EXPLO_POP; i++)
487 		{
488 			alSourcef (  sourceExploPop[i], AL_GAIN, (0.2+(FRAND*0.8))*gain[Explosion]*soundVolume);
489 		}
490 	}
491 }
492 
493 /**
494  * adjust gain of OpenAL music. Also adjusts CD channel of hardware
495  * mixer if appropriate OpenAL extensions are available.
496  */
497 //----------------------------------------------------------
setMusicVolume(float vol)498 void AudioOpenAL::setMusicVolume(float vol)
499 {
500 	Config	*config = Config::instance();
501 	if(config->audioEnabled() == true)
502 	{
503 		if(vol > 1.0) vol = 1.0;
504 		if(vol < 0.0) vol = 0.0;
505 		musicVolume = vol;
506 		alSourcef ( source[MusicGame], AL_GAIN, gain[MusicGame]*musicVolume);
507 		alSourcef ( source[MusicMenu], AL_GAIN, gain[MusicGame]*musicVolume);
508 #ifdef USE_SDL_CDROM
509 #ifdef CD_VOLUME
510 		if(cdrom && alcSetAudioChannel)
511 		{
512 			alcSetAudioChannel(ALC_CHAN_CD_LOKI, musicVolume);
513 		}
514 #endif
515 #endif // USE_SDL_CDROM
516 		if( config->debug() ) fprintf(stderr, _("Music volume = %f\n"), vol);
517 	}
518 }
519 
520 /**
521  * load WAV sound effects
522  */
523 //----------------------------------------------------------
loadSounds()524 void AudioOpenAL::loadSounds()
525 {
526 	int i;
527 
528 	for(i = 0; i < NumSoundTypes; i++)
529 	{
530 		if(!fileNames[i])
531 		{
532 			fprintf(stderr, _("\nERROR! - sound enumerant index %d does not have valid filename!\n"), i);
533 		}
534 		else
535 		{
536 #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
537 			buffer[i] = alutCreateBufferFromFile(dataLoc(fileNames[i]));
538 			if( buffer[i] == AL_NONE ) checkError();
539 #else
540 			ALsizei size, freq;
541 			ALenum format;
542 			ALvoid *data;
543 			ALboolean loop;
544 #ifndef _WIN32
545 #ifdef __APPLE__
546 			alutLoadWAVFile(const_cast<ALbyte*>(dataLoc(fileNames[i])), &format, &data, &size, &freq);
547 #else
548 			alutLoadWAVFile(const_cast<ALbyte*>(dataLoc(fileNames[i])), &format, &data, &size, &freq, &loop);
549 #endif
550 			alBufferData (buffer[i], format, data, size, freq);
551 			alutUnloadWAV(format,data,size,freq);
552 #else //_WIN32
553 			char nameBuffer[256];
554 			sprintf(nameBuffer, "%s", dataLoc(fileNames[i]));
555 			if( config->debug() ) fprintf(stderr, _("alutLoadWAVFile(\"%s\",...);\n"), nameBuffer);
556 			alutLoadWAVFile(nameBuffer,&format,&data,&size,&freq);
557 			alBufferData(buffer[i],format,data,size,freq);
558 			alutUnloadWAV(format,data,size,freq);
559 #endif//_WIN32
560 #endif
561 		}
562 	}
563 }
564 
565 //----------------------------------------------------------
checkError(const char * tag)566 void AudioOpenAL::checkError(const char* tag)
567 {
568 	ALenum	error = alGetError();
569 	if(error != AL_NO_ERROR)
570 	{
571 		fprintf(stderr, _("ERROR!! <%s> alGetError() = %s\n"), tag, alGetString(error) );
572 	}
573 	ALCenum error2 = alcGetError(dev);
574 	if(error2 != ALC_NO_ERROR)
575 	{
576 		fprintf(stderr, _("ERROR!! <%s> alcGetError() = %s\n"), tag, alcGetString(dev, error2) );
577 	}
578 	error = alutGetError();
579 	if(error != ALUT_ERROR_NO_ERROR)
580 	{
581 		fprintf(stderr, _("ERROR!! <%s> alutGetError() = %s\n"), tag, alutGetErrorString(error) );
582 	}
583 }
584 
585 /**
586  * This should be called every frame to ensure that delayed sounds are played
587  * and that the numReqThisFrame counter is reset to 0
588  */
589 //----------------------------------------------------------
update()590 void AudioOpenAL::update()
591 {
592 	SoundInfo *sound;
593 	SoundInfo *nextSound;
594 	SoundInfo *backSound;
595 
596 	// play any delayed sounds
597 	sound = soundQueue->next;
598 	while(sound)
599 	{
600 		sound->age++;
601 		if(sound->age >= 0)
602 		{
603 			backSound = sound->back;
604 			nextSound = sound->next;
605 			backSound->next = nextSound;
606 			if(nextSound)
607 				nextSound->back = backSound;
608 			playSound(sound->type, sound->pos);
609 			delete sound;
610 			sound = backSound;
611 		}
612 		sound = sound->next;
613 	}
614 
615 	// reset the number of requests to 0
616 	for(int i = 0; i < NumSoundTypes; i++)
617 	{
618 		numReqThisFrame[i] = 0;
619 	}
620 }
621 
622 /**
623  * play sound of a given type.
624  * @param type type of sound to play
625  * @param pos position of the sound in world coords
626  * @param age If age is negative, playback of the sound will
627  * be delayed |age| frames.
628  */
629 //----------------------------------------------------------
playSound(SoundType type,float * pos,int age)630 void AudioOpenAL::playSound(SoundType type, float *pos, int age)
631 {
632 	Config	*config = Config::instance();
633 	if(config->audioEnabled())
634 	{
635 		float p[3];
636 		p[0] =  pos[0]*audioScale[0];
637 		p[1] =  pos[1]*audioScale[1];
638 		p[2] =  pos[2]*audioScale[2];
639 
640 		if(age >= 0)
641 		{
642 			numReqThisFrame[type]++;
643 			// only play one sound of any given type per frame...
644 			if(numReqThisFrame[type] < 2)
645 			{
646 				switch(type)
647 				{
648 					case Explosion:
649 						playSoundExplosion(p);
650 						break;
651 					case ExploPop:
652 						playSoundExploPop(p);
653 						break;
654 					default:
655 						alSourceStop(source[type]);
656 						alSourcefv( source[type], AL_POSITION, p );
657 						alSourcePlay(source[type]);
658 //						fprintf(stderr, _("play %d\n"), type);
659 						break;
660 				}
661 			}
662 		}
663 		else
664 		{
665 			SoundInfo *first = soundQueue->next;
666 			SoundInfo *newSound;
667 			newSound = new SoundInfo(type, pos, age);
668 			newSound->back = soundQueue;
669 			newSound->next = soundQueue->next;
670 			soundQueue->next = newSound;
671 			if(first)
672 				first->back = newSound;
673 		}
674 	}
675 }
676 
677 //----------------------------------------------------------
playSoundExplosion(float p[3])678 void AudioOpenAL::playSoundExplosion(float p[3])
679 {
680 	explosionIndex++;
681 	explosionIndex = explosionIndex%NUM_EXPLO;
682 
683 	alSourceStop(sourceExplosion[explosionIndex]);
684 	alSourcefv  (sourceExplosion[explosionIndex], AL_POSITION, p );
685 	alSourcePlay(sourceExplosion[explosionIndex]);
686 }
687 
688 //----------------------------------------------------------
playSoundExploPop(float p[3])689 void AudioOpenAL::playSoundExploPop(float p[3])
690 {
691 	p[0] *= 1.5;
692 	exploPopIndex++;
693 	exploPopIndex = exploPopIndex%NUM_EXPLO_POP;
694 
695 	alSourceStop(sourceExploPop[exploPopIndex]);
696 	alSourcefv  (sourceExploPop[exploPopIndex], AL_POSITION, p );
697 	alSourcePlay(sourceExploPop[exploPopIndex]);
698 }
699 
700 //----------------------------------------------------------
loadMusicList()701 void AudioOpenAL::loadMusicList()
702 {
703 	Config	*config = Config::instance();
704 	int		i;
705 	int		lineCount = 0;
706 	char	buffer[1024];
707 	char	configFilename[256];
708 	FILE	*file;
709 
710 	const char *homeDir = getenv("HOME");
711 	if(!homeDir)
712 		homeDir = "./";
713 
714 	musicMax = 0;
715 	musicIndex = 0;
716 	sprintf(configFilename, "%s/%s", homeDir, CONFIG_MUSIC_FILE);
717 	alterPathForPlatform(configFilename);
718 	file = fopen(configFilename, "r");
719 	if(!file)
720 	{
721 		char	configOldFilename[256];
722 		sprintf(configOldFilename, "%s/.chromium-music" CONFIG_EXT, homeDir);
723 		alterPathForPlatform(configOldFilename);
724 		rename(configOldFilename,configFilename);
725 		file = fopen(configFilename, "r");
726 	}
727 
728 	if(file)
729 	{
730 		while( fgets(buffer, 1024, file) )
731 		{
732 			int tmp = strlen(buffer);
733 			buffer[tmp-1] = '\0'; //-- get rid of new line
734 
735 			lineCount++;
736 			if(strlen(buffer) > 255)
737 			{
738 				fprintf(stderr, _("ERROR: filename too long: \"%s\", line %d\n"), configFilename, lineCount);
739 			}
740 			else if(strlen(buffer) > 4)
741 			{
742 				switch(extensionFormat(buffer))
743 				{
744 					case WAV:
745 						strcpy(musicFile[musicMax], buffer);
746 						musicMax++;
747 						break;
748 					case MP3:
749 						if(alutLoadMP3)
750 						{
751 							strcpy(musicFile[musicMax], buffer);
752 							musicMax++;
753 						}
754 						else
755 						{
756 							fprintf(stderr, _("WARNING: MP3 support not available: \"%s\", line %d\n"), configFilename, lineCount);
757 						}
758 						break;
759 					case OGG:
760 						if(alutLoadVorbis)
761 						{
762 							strcpy(musicFile[musicMax], buffer);
763 							musicMax++;
764 						}
765 						else
766 						{
767 							fprintf(stderr, _("WARNING: Ogg/Vorbis support not available: \"%s\", line %d\n"), configFilename, lineCount);
768 						}
769 						break;
770 					default:
771 						fprintf(stderr, _("WARNING: file type not recognized: \"%s\": \"%s\", line %d\n"), buffer, configFilename, lineCount);
772 						break;
773 				}
774 			}
775 			if(musicMax+1 >= MAX_MUSIC) // limited music array size.
776 				break;
777 		}
778 		fclose(file);
779 		file = NULL;
780 	}
781 	else
782 		config->setUsePlayList(false);
783 	if(musicMax < 1)
784 		config->setUsePlayList(false);
785 
786 	fprintf(stderr, _("music playlist:\n"));
787 	for(i = 0; i < musicMax; i++)
788 	{
789 		fprintf(stderr, _(" %2d : %s\n"), i+1, musicFile[i]);
790 	}
791 	fprintf(stderr, _("loaded %s\n"), configFilename);
792 }
793 
794 /**
795  * Set music track to index. If CDROM is enabled, calls Audio::setMusicIndex().
796  * If playList is enabled, set to Nth track.
797  */
798 //----------------------------------------------------------
setMusicIndex(int index)799 void AudioOpenAL::setMusicIndex(int index)
800 {
801 	Config	*config = Config::instance();
802 	bool	wasPlaying = false;
803 
804 	if(musicMax)
805 		musicIndex = index%musicMax;
806 
807 #ifdef USE_SDL_CDROM
808 	if(initialized && cdrom)
809 #else
810 	if(initialized)
811 #endif // USE_SDL_CDROM
812 	{
813 		Audio::	setMusicIndex(index);
814 	}
815 	else if(initialized && config->usePlayList())
816 	{
817 		bool loadSuccess = true;
818 		if(config->audioEnabled())
819 		{
820 			checkError(_("AudioOpenAL::setMusicIndex -- begin"));
821 			//-- if music is currently playing, we want to
822 			//   re-start playing after loading new song
823 			ALint state = AL_INITIAL;
824 #ifdef OLD_OPENAL
825 			alGetSourcei(source[MusicGame], AL_SOURCE_STATE, &state);
826 #else
827 			alGetSourceiv(source[MusicGame], AL_SOURCE_STATE, &state);
828 #endif
829 			if(state == AL_PLAYING)
830 				wasPlaying = true;
831 
832 			alSourceStop(source[MusicGame]);
833 			checkError(_("AudioOpenAL::setMusicIndex -- before setting source buffer to 0"));
834 			alSourcei(source[MusicGame], AL_BUFFER, 0);
835 //			alSourcei(source[MusicGame], AL_BUFFER, AL_NONE);
836 			checkError(_("AudioOpenAL::setMusicIndex -- after setting source buffer to 0"));
837 			alDeleteBuffers(1 , &buffer[MusicGame]);
838 			alGenBuffers(1, &buffer[MusicGame]);
839 			switch(extensionFormat(musicFile[musicIndex]))
840 			{
841 				case WAV:
842 					loadSuccess = loadWAV(musicFile[musicIndex]);
843 					break;
844 				case MP3:
845 					loadSuccess = loadMP3(musicFile[musicIndex]);
846 					break;
847 				case OGG:
848 					loadSuccess = loadVorbis(musicFile[musicIndex]);
849 					break;
850 				default:
851 					loadSuccess = false;
852 					break;
853 			}
854 			if(loadSuccess)
855 			{
856 				ALfloat pos[] = { 0.0, -5.0,  25.0 };
857 				alSourcei ( source[MusicGame], AL_BUFFER, buffer[MusicGame]);
858 				alSourcefv( source[MusicGame], AL_POSITION, pos );
859 				alSourcef ( source[MusicGame], AL_GAIN, gain[MusicGame]*musicVolume);
860 				alSourcei ( source[MusicGame], AL_LOOPING, AL_TRUE);
861 				if(wasPlaying)
862 					alSourcePlay(source[MusicGame]);
863 
864 			}
865 			else
866 			{
867 				//-- fall back to default loop
868 				loadSuccess = loadWAV(dataLoc(fileNames[MusicGame]));
869 			}
870 		}
871 		checkError(_("AudioOpenAL::setMusicIndex -- end"));
872 	}
873 	else if(initialized)
874 	{
875 		ALint state = AL_INITIAL;
876 #ifdef OLD_OPENAL
877 		alGetSourcei(source[MusicGame], AL_SOURCE_STATE, &state);
878 #else
879 		alGetSourceiv(source[MusicGame], AL_SOURCE_STATE, &state);
880 #endif
881 		if(state == AL_PLAYING)
882 			wasPlaying = true;
883 		alSourceStop(source[MusicGame]);
884 		if(wasPlaying)
885 			alSourcePlay(source[MusicGame]);
886 	}
887 }
888 
889 #ifndef __linux__
890 // kludge so things compile on Win32 and Mac
strcasecmp(const char * a,const char * b)891 int strcasecmp(const char *a, const char *b)
892 {
893 	return strcmp(a, b);
894 }
895 #endif
896 
897 //----------------------------------------------------------
extensionFormat(char * filename)898 AudioOpenAL::AudioFormat AudioOpenAL::extensionFormat(char* filename)
899 {
900 	AudioFormat retVal = Unknown;
901 	char *walker;
902 	walker = strrchr(filename, '.');
903 	if(walker)
904 	{
905 		if     (strcasecmp(walker, ".wav") == 0)
906 			retVal = WAV;
907 		else if(strcasecmp(walker, ".mp3") == 0)
908 			retVal = MP3;
909 		else if(strcasecmp(walker, ".ogg") == 0)
910 			retVal = OGG;
911 	}
912 	else
913 		retVal = Unknown;
914 
915 	return retVal;
916 }
917 //----------------------------------------------------------
loadWAV(const char * filename)918 bool AudioOpenAL::loadWAV(const char *filename)
919 {
920 #ifndef USE_PLAYLIST
921 	fprintf(stderr, _("WARNING: PlayList support not compiled in (AudioOpenAL.cpp): %s\n"), filename);
922 	return false;
923 #else //USE_PLAYLIST
924 #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
925 	buffer[MusicGame] = alutCreateBufferFromFile(filename);
926 	if( buffer[MusicGame] == AL_NONE ) checkError();
927 	return buffer[MusicGame] != AL_NONE;
928 #else
929 	bool retVal;
930 	ALsizei size, freq;
931 	ALenum format;
932 	ALvoid *data;
933 	ALboolean loop;
934 #ifdef __APPLE__
935 	alutLoadWAVFile(const_cast<ALbyte*>(filename), &format, &data, &size, &freq);
936 #else
937 	alutLoadWAVFile(const_cast<ALbyte*>(filename), &format, &data, &size, &freq, &loop);
938 #endif
939 	retVal = (alGetError() == AL_NO_ERROR);
940 	if(retVal)
941 	{
942 		alBufferData (buffer[MusicGame], format, data, size, freq);
943 		alutUnloadWAV(format,data,size,freq);
944 	}
945 	return retVal;
946 #endif
947 #endif//USE_PLAYLIST
948 }
949 
950 //----------------------------------------------------------
loadMP3(const char * filename)951 bool AudioOpenAL::loadMP3(const char *filename)
952 {
953 #ifndef USE_PLAYLIST
954 	fprintf(stderr, _("WARNING: PlayList support not compiled in (AudioOpenAL.cpp): %s\n"), filename);
955 	return false;
956 #else//USE_PLAYLIST
957 	FILE	*file;
958 	struct	stat sbuf;
959 	size_t		size;
960 	void	*data;
961 
962 	if(stat(filename, &sbuf) == -1)
963 	{
964 		perror(filename);
965 		return false;
966 	}
967 	size = sbuf.st_size;
968 	data = malloc(size);
969 	if(!data)
970 	{
971 		fprintf(stderr, _("ERROR: Could not allocate memory in AudioOpenAL::loadMP3\n"));
972 		return false;
973 	}
974 	file = fopen(filename, "rb");
975 	if(!file)
976 	{
977 		fprintf(stderr, _("ERROR: Could not open \"%s\" in AudioOpenAL::loadMP3\n"), filename);
978 		free(data);
979 		return false;
980 	}
981 	if( fread(data, 1, size, file) != size )
982 	{
983 		fprintf(stderr, _("ERROR: Could not read from \"%s\" in AudioOpenAL::loadMP3\n"), filename);
984 		fclose(file);
985 		free(data);
986 		return false;
987 	}
988 	fclose(file);
989 	if( !(alutLoadMP3(buffer[MusicGame], data, size)) )
990 	{
991 		fprintf(stderr, _("ERROR: alutLoadMP3() failed in AudioOpenAL::loadMP3\n"));
992 		free(data);
993 		return false;
994 	}
995 	free(data);
996 	return true;
997 #endif//USE_PLAYLIST
998 }
999 
1000 //----------------------------------------------------------
loadVorbis(const char * filename)1001 bool AudioOpenAL::loadVorbis(const char *filename)
1002 {
1003 #ifndef USE_PLAYLIST
1004 	fprintf(stderr, _("WARNING: PlayList support not compiled in (AudioOpenAL.cpp): %s\n"), filename);
1005 	return false;
1006 #else//USE_PLAYLIST
1007 	if(initialized)
1008 	{
1009 		FILE	*file;
1010 		struct	stat sbuf;
1011 		size_t		size;
1012 		void	*data;
1013 
1014 		if(stat(filename, &sbuf) == -1)
1015 		{
1016 			perror(filename);
1017 			return false;
1018 		}
1019 		size = sbuf.st_size;
1020 		data = malloc(size);
1021 		if(!data)
1022 		{
1023 			fprintf(stderr, _("ERROR: Could not allocate memory in AudioOpenAL::loadVorbis\n"));
1024 			return false;
1025 		}
1026 		file = fopen(filename, "rb");
1027 		if(!file)
1028 		{
1029 			fprintf(stderr, _("ERROR: Could not open \"%s\" in AudioOpenAL::loadVorbis\n"), filename);
1030 			free(data);
1031 			return false;
1032 		}
1033 		if( fread(data, 1, size, file) != size )
1034 		{
1035 			fprintf(stderr, _("ERROR: Could not read from \"%s\" in AudioOpenAL::loadVorbis\n"), filename);
1036 			fclose(file);
1037 			free(data);
1038 			return false;
1039                 }
1040 		fclose(file);
1041 		if( !(alutLoadVorbis(buffer[MusicGame], data, size)) )
1042 		{
1043 			fprintf(stderr, _("ERROR: alutLoadVorbis() failed in AudioOpenAL::loadVorbis\n"));
1044 			free(data);
1045 			return false;
1046 		}
1047 		free(data);
1048 		return true;
1049 	}
1050 	else
1051 		return false;
1052 #endif//USE_PLAYLIST
1053 }
1054 
1055 #endif // AUDIO_OPENAL
1056 
1057 
1058