cpp_photon/src/audio/AudioCore.cpp
2005-07-05 06:44:55 +00:00

155 lines
3.9 KiB
C++

//This file is part of Photon (http://photon.sourceforge.net)
//Copyright (C) 2004-2005 James Turk
//
// Author:
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: AudioCore.cpp,v 1.7 2005/07/05 06:44:56 cozman Exp $
#ifdef PHOTON_USE_OPENAL
#include "audio/AudioCore.hpp"
#include <string>
#include "exceptions.hpp"
namespace photon
{
namespace audio
{
AudioCore::AudioCore()
{
util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?)
util::ensureVersion("OpenAL", initOpenAL(), oalReq);
}
AudioCore::~AudioCore()
{
// retrieve both the context and device
ALCcontext* context( alcGetCurrentContext() );
ALCdevice* device( alcGetContextsDevice(context) );
// set current context to null
alcMakeContextCurrent(0);
// destroy context & device
alcDestroyContext(context);
alcCloseDevice(device);
}
std::string AudioCore::getAudioDeviceName() const
{
ALCdevice* device (alcGetContextsDevice( alcGetCurrentContext() ));
std::string name ( reinterpret_cast<const char*>(
alcGetString(device, ALC_DEVICE_SPECIFIER)) );
return name;
}
std::string AudioCore::checkOpenALError()
{
ALenum errCode = alGetError();
std::string err;
switch(errCode)
{
case AL_NO_ERROR:
// do nothing
break;
case AL_INVALID_NAME:
err = "Invalid name/ID parameter in OpenAL call";
break;
case AL_INVALID_ENUM:
err = "Invalid enum parameter in OpenAL call";
break;
case AL_INVALID_VALUE:
err = "Invalid value parameter in OpenAL call";
break;
case AL_INVALID_OPERATION:
err = "Invalid OpenAL operation";
break;
case AL_OUT_OF_MEMORY:
err = "OpenAL out of memory";
break;
default:
err = "Unknown OpenAL error";
break;
}
return err;
}
void AudioCore::throwOpenALError(const std::string& func)
{
std::string err( checkOpenALError() );
if(err.length())
{
throw APIError(err + " within " + func);
}
}
util::VersionInfo AudioCore::initOpenAL()
{
ALCdevice* device(0);
ALCcontext* context(0);
std::stringstream ss; // stream for parsing version
std::string junks; // junk string for parsing
char junkc; // junk character for parsing
uint major,minor,patch; // version numbers
// obtain default device if no deviceName is set, otherwise use deviceName
device = alcOpenDevice(deviceName_.empty() ? 0 :
reinterpret_cast<const ALubyte*>(deviceName_.c_str()) );
if(device == 0)
{
throw APIError("Failed to obtain OpenAL device " + deviceName_ + ": " +
checkOpenALError());
}
// create context
context = alcCreateContext(device,0);
if(context == 0)
{
throw APIError("Failed to obtain an OpenAL context: " +
checkOpenALError());
}
alcMakeContextCurrent(context); // context must be current to get version
// setup listener to default position
ALfloat posvel[] = { 0.0, 0.0, 0.0 };
ALfloat ori[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
alListenerfv(AL_POSITION, posvel);
alListenerfv(AL_VELOCITY, posvel);
alListenerfv(AL_ORIENTATION, ori);
ss << alGetString(AL_VERSION);
#if defined(WINVER)
ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0"
#elif defined(linux)
ss >> major >> junkc >> minor >> junkc >> patch;
#else
#warning OpenAL only built on Windows/Linux, find out version on OSX
#endif
return util::VersionInfo(major,minor,patch);
}
void AudioCore::setDesiredDevice(const std::string& name)
{
// deviceName_ is used inside initOpenAL, must be set prior to construction
// or not set at all (in which case default device will be used)
deviceName_ = name;
}
std::string AudioCore::deviceName_;
}
}
#endif //PHOTON_USE_OPENAL