/**
* @class Audio
* @brief The UOP audio subsystem
* @author Samuel Kaufman
* @date 2002
*/
/*****
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****/
#include "uop.h"
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "audio.h"
#include "uopconfig.h"
extern UOPConfig *config;
AudioMessage::AudioMessage(AMessageHeader header)
{
this->header = header;
body = NULL;
next = NULL;
}
Audio::Audio()
{
messagesLock = SDL_CreateMutex();
messages = NULL;
audioPump = NULL;
curMusic = NULL;
musicOn = false;
soundOn = false;
}
Audio::~Audio()
{
if (audioPump)
shutdown();
SDL_DestroyMutex(messagesLock);
}
void Audio::start()
{
if (!(config->getBoolean("SoundOn")||config->getBoolean("MusicOn")))
return;
if (Mix_OpenAudio(22050, AUDIO_S16, 2, 4096)) {
cerr << "Unable to open audio: " << SDL_GetError() << endl;
return;
}
audioPump = SDL_CreateThread(audioThread, this);
// Music initialization
// ------------------------
if (!config->getBoolean("MusicOn"))
return;
ifstream lookupfile;
// TODO: Have a Registry entry added with data dir in Windows
#ifdef HAVE_CONFIG_H
string fullpath = DATADIR;
#else
string fullpath = "./";
#endif
fullpath += "/musicmap.def";
lookupfile.open(fullpath.c_str());
if (!lookupfile.is_open())
{
lookupfile.open("musicmap.def");
if (!lookupfile.is_open())
{
cerr << "Couldn't open " << fullpath.c_str()
<< " or ./musicmap.def" << endl
<< "Music will be disabled for this session" << endl;
return;
}
}
while (1)
{
if (!lookupfile.good())
break;
string buf;
lookupfile >> buf;
if (buf.size() != 0)
lookupTable.push_back(buf);
}
musicOn = true;
lookupfile.close();
}
void Audio::shutdown()
{
Mix_CloseAudio();
if (audioPump)
{
int exitCode;
AudioMessage *message = new AudioMessage(Shutdown);
addMessage(message);
SDL_WaitThread(audioPump, &exitCode);
if (exitCode)
{
cerr << "Warning: Audio subsystem exited with abnormal exit code: "
<< exitCode << endl;
}
}
AudioMessage *cur = messages;
while (cur != NULL)
{
AudioMessage *dest = cur->next;
delete cur;
cur = dest;
}
}
void Audio::playMusic(Uint16 musicID)
{
if ((audioPump == NULL) || (musicOn != true))
return;
AudioMessage *mesg = new AudioMessage(PlayMusic);
Uint16 *mBuf = new Uint16;
*mBuf = musicID;
mesg->body = (char*)mBuf;
addMessage(mesg);
}
void Audio::stopMusic()
{
if (audioPump == NULL)
return;
AudioMessage *mesg = new AudioMessage(StopMusic);
addMessage(mesg);
}
void Audio::addMessage(AudioMessage *newMessage)
{
SDL_mutexP(messagesLock);
if (!messages)
messages = newMessage;
else
{
AudioMessage *cur = messages;
while (cur->next != NULL)
cur = cur->next;
cur->next = newMessage;
}
SDL_mutexV(messagesLock);
}
string Audio::getMusicPath(string name)
{
string buf;
buf=config->encapDatLoc("music/"+name+".mid");
return buf;
}
int audioThread(void *audioSystem)
{
Audio *audio = (Audio*)audioSystem;
while (1)
{
SDL_mutexP(audio->messagesLock);
if (audio->messages)
{
AudioMessage *cur = audio->messages;
while (cur != NULL)
{
AudioMessage *dest = cur->next;
switch (cur->header)
{
case PlayMusic:
if (audio->curMusic != NULL)
{
Mix_FadeOutMusic(1000);
Mix_FreeMusic(audio->curMusic);
}
audio->curMusic = Mix_LoadMUS(audio->getMusicPath(*cur->body).c_str());
Mix_PlayMusic(audio->curMusic, 0);
break;
case StopMusic:
if (audio->curMusic != NULL)
{
Mix_FadeOutMusic(1000);
Mix_FreeMusic(audio->curMusic);
}
break;
case Shutdown:
return 0;
}
delete cur;
cur = dest;
}
}
audio->messages = NULL;
SDL_mutexV(audio->messagesLock);
SDL_Delay(100); // Anti CPU hog
}
return 1; // This should never happen
}