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