f0236ddab0
1158 on 0.3rc1). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1159 178a84e3-b1eb-0310-8ba1-8eac791a3b58
333 lines
8.4 KiB
C++
333 lines
8.4 KiB
C++
// $Id$
|
|
//
|
|
// SuperTuxKart - a fun racing game with go-kart
|
|
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
|
|
//
|
|
// 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.
|
|
|
|
#if HAVE_OPENAL && HAVE_MIKMOD
|
|
|
|
#ifdef __APPLE__
|
|
# include <OpenAL/al.h>
|
|
#else
|
|
# include <AL/al.h>
|
|
#endif
|
|
#include <AL/alut.h>
|
|
|
|
#include "music_mikmod.hpp"
|
|
#include "loader.hpp"
|
|
#include "user_config.hpp"
|
|
|
|
#define BUFFER_SIZE (1024 * 32)
|
|
|
|
|
|
MusicMikMod::MusicMikMod()
|
|
{
|
|
m_modStream= NULL;
|
|
m_soundBuffers[0]= m_soundBuffers[1]= 0;
|
|
m_soundSource= 0;
|
|
m_pausedMusic= true;
|
|
|
|
static bool initialized = false;
|
|
if( !initialized )
|
|
{
|
|
initialized = true;
|
|
|
|
//Register network drivers
|
|
MikMod_RegisterDriver(&drv_AF);
|
|
MikMod_RegisterDriver(&drv_esd);
|
|
|
|
//Register hardware drivers, but disk writer drivers cause problems
|
|
//on computers without proper hardware or network drivers.
|
|
MikMod_RegisterDriver(&drv_aix);
|
|
MikMod_RegisterDriver(&drv_alsa);
|
|
MikMod_RegisterDriver(&drv_hp);
|
|
MikMod_RegisterDriver(&drv_sam9407);
|
|
MikMod_RegisterDriver(&drv_sgi);
|
|
MikMod_RegisterDriver(&drv_sun);
|
|
MikMod_RegisterDriver(&drv_ultra);
|
|
|
|
//These two won't link, at least under Gentoo linux.
|
|
//MikMod_RegisterDriver(&drv_dart);
|
|
//MikMod_RegisterDriver(&drv_os2);
|
|
|
|
//Register the null driver in case sound is not available.
|
|
//Also, for some reason, the assert at line 76 of this file
|
|
//crashes the program without it.
|
|
MikMod_RegisterDriver(&drv_nos);
|
|
|
|
// register loaders (it, s3m, xm y mod)
|
|
MikMod_RegisterAllLoaders();
|
|
}
|
|
|
|
if(MikMod_Init(""))
|
|
{
|
|
user_config->setMusic(UserConfig::UC_TEMPORARY_DISABLE);
|
|
fprintf(stderr,"Problems initialising mikmod. Disabling music.\n");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
MusicMikMod::~MusicMikMod()
|
|
{
|
|
stopMusic();
|
|
if(!release())
|
|
{
|
|
fprintf(stderr,"Problems with mikmod:release.\n");
|
|
}
|
|
MikMod_Exit();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::load(const char* filename)
|
|
{
|
|
if(!release())
|
|
{
|
|
user_config->setMusic(UserConfig::UC_TEMPORARY_DISABLE);
|
|
fprintf(stderr,"Problems mikmod:release. Disabling music.\n");
|
|
return false;
|
|
}
|
|
|
|
|
|
m_fileName = loader->getPath(filename);
|
|
FILE* modFile = fopen(m_fileName.c_str(), "rb");
|
|
if (modFile == NULL)
|
|
{
|
|
fprintf(stderr, "Loading Music: %s failed\n", m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
m_modStream= Player_LoadFP(modFile, 255, 0);
|
|
|
|
fclose(modFile);
|
|
if (m_modStream == NULL)
|
|
{
|
|
fprintf(stderr, "Loading Music: %s failed\n", m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
Player_Start(m_modStream);
|
|
|
|
alGenBuffers(2, m_soundBuffers);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
fprintf(stderr, "Loading Music: %s failed\n", m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
alGenSources(1, &m_soundSource);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
fprintf(stderr, "Loading Music: %s failed\n", m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0);
|
|
alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0);
|
|
alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0);
|
|
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, 0.0 );
|
|
alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE );
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::release()
|
|
{
|
|
if (m_fileName == "")
|
|
{
|
|
// nothing is loaded
|
|
return true;
|
|
}
|
|
m_fileName= "";
|
|
|
|
alSourceStop(m_soundSource);
|
|
|
|
// empty
|
|
int queued= 0;
|
|
alGetSourcei(m_soundSource, AL_BUFFERS_QUEUED, &queued);
|
|
while(queued--)
|
|
{
|
|
ALuint buffer= 0;
|
|
alSourceUnqueueBuffers(m_soundSource, 1, &buffer);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
alDeleteSources(1, &m_soundSource);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
alDeleteBuffers(2, m_soundBuffers);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Player_Free(m_modStream);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::playMusic()
|
|
{
|
|
if(isPlaying())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!streamIntoBuffer(m_soundBuffers[0]))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(!streamIntoBuffer(m_soundBuffers[1]))
|
|
{
|
|
return false;
|
|
}
|
|
alSourceQueueBuffers(m_soundSource, 2, m_soundBuffers);
|
|
|
|
alSourcePlay(m_soundSource);
|
|
m_pausedMusic= false;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::isPlaying()
|
|
{
|
|
ALenum state;
|
|
alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
|
|
return (state == AL_PLAYING);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::stopMusic()
|
|
{
|
|
pauseMusic();
|
|
release();
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::pauseMusic()
|
|
{
|
|
if (m_fileName == "")
|
|
{
|
|
// nothing is loaded
|
|
return true;
|
|
}
|
|
|
|
alSourceStop(m_soundSource);
|
|
m_pausedMusic= true;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::resumeMusic()
|
|
{
|
|
if (m_fileName == "")
|
|
{
|
|
// nothing is loaded
|
|
return true;
|
|
}
|
|
|
|
alSourcePlay(m_soundSource);
|
|
m_pausedMusic= false;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void MusicMikMod::update()
|
|
{
|
|
if (m_pausedMusic)
|
|
{
|
|
// nothing todo
|
|
return;
|
|
}
|
|
|
|
int processed= 0;
|
|
alGetSourcei(m_soundSource, AL_BUFFERS_PROCESSED, &processed);
|
|
|
|
bool active= true;
|
|
while(processed--)
|
|
{
|
|
ALuint buffer;
|
|
alSourceUnqueueBuffers(m_soundSource, 1, &buffer);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
user_config->setMusic(UserConfig::UC_TEMPORARY_DISABLE);
|
|
fprintf(stderr,"Problems with mikmod:sourceUnqueueBuffers. Disabling music.\n");
|
|
return;
|
|
}
|
|
|
|
active= streamIntoBuffer(buffer);
|
|
alSourceQueueBuffers(m_soundSource, 1, &buffer);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
user_config->setMusic(UserConfig::UC_TEMPORARY_DISABLE);
|
|
fprintf(stderr,"Problems with mikmod:sourceQueueBuffers. Disabling music.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// check for underrun
|
|
if (active)
|
|
{
|
|
// we have data, so we should be playing...
|
|
|
|
ALenum state;
|
|
alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
|
|
if (state != AL_PLAYING)
|
|
{
|
|
alGetSourcei(m_soundSource, AL_BUFFERS_PROCESSED, &processed);
|
|
alSourcePlay(m_soundSource);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no more data. Seek to beginning -> loop
|
|
Player_SetPosition(m_modStream->reppos);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool MusicMikMod::streamIntoBuffer(ALuint buffer)
|
|
{
|
|
SBYTE pcm[BUFFER_SIZE];
|
|
|
|
// write bytes in pcm
|
|
VC_WriteBytes(pcm, BUFFER_SIZE);
|
|
|
|
if (!Player_Active())
|
|
{
|
|
// there aren't bytes that we could write in pcm
|
|
return false;
|
|
}
|
|
|
|
alBufferData(buffer, AL_FORMAT_STEREO16, (char*)pcm, BUFFER_SIZE, md_mixfreq);
|
|
if (alGetError() != AL_NO_ERROR)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif // HAVE_OPENAL && HAVE_MIKMOD
|
|
|