09c4314a05
removed 7z and made setup page for AMS
663 lines
16 KiB
C++
663 lines
16 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#include "sound_plugin.h"
|
|
#include "sound_document_plugin.h"
|
|
#include "resource.h"
|
|
//#include "sound/driver/buffer.h"
|
|
#include "nel/misc/vector.h"
|
|
#include "nel/misc/path.h"
|
|
#include "nel/sound/u_source.h"
|
|
#include "loading_dialog.h"
|
|
#include "nel/ligo/primitive.h"
|
|
|
|
#include "nel/sound/sound.h"
|
|
#include "nel/sound/simple_sound.h"
|
|
#include <afxcmn.h>
|
|
|
|
using namespace std;
|
|
using namespace NLSOUND;
|
|
using namespace NLMISC;
|
|
|
|
|
|
|
|
namespace NLGEORGES
|
|
{
|
|
|
|
|
|
|
|
// ***************************************************************************
|
|
/*
|
|
__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface)
|
|
{
|
|
// Same version ?
|
|
if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION)
|
|
{
|
|
return new CSoundPlugin(globalInterface);
|
|
}
|
|
else
|
|
{
|
|
MessageBox (NULL, "Plugin version invalid.", "Sound plugin for georges editor", MB_OK|MB_ICONEXCLAMATION);
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
// ***************************************************************************
|
|
|
|
CSoundPlugin::CSoundPlugin(IEdit *globalInterface)
|
|
: _Source(NULL),
|
|
_Sound(NULL),
|
|
_FreeSound(false),
|
|
_ActiveDoc(NULL),
|
|
_InvalidSound(false)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Initialize without sheet id bin
|
|
NLMISC::CSheetId::initWithoutSheet();
|
|
|
|
CVector dir;
|
|
|
|
_GlobalInterface = globalInterface;
|
|
/* _SoundDriver = ISoundDriver::createDriver();
|
|
_Listener = _SoundDriver->createListener();
|
|
_Listener->setRolloffFactor(1.0f);
|
|
_Source = _SoundDriver->createSource();
|
|
dir.set(0, 1, 0);
|
|
_Source->setDirection(dir);
|
|
_Buffer = 0;
|
|
*/
|
|
|
|
CLoadingDialog loadDlg;
|
|
|
|
loadDlg.Create(IDD_DIALOG_LOADING);
|
|
loadDlg.Message = "";
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.ShowWindow(SW_SHOW);
|
|
|
|
CConfigFile &cf = globalInterface->getConfigFile();
|
|
// Add the search path
|
|
try
|
|
{
|
|
CConfigFile::CVar *psearchPath = cf.getVarPtr("SearchPath");
|
|
if (psearchPath != 0)
|
|
{
|
|
for (uint i=0; i<psearchPath->size(); ++i)
|
|
{
|
|
string path = psearchPath->asString(i);
|
|
loadDlg.Message = (string("Adding search path \"")+path+"\"").c_str();
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.RedrawWindow();
|
|
NLMISC::CPath::addSearchPath(path, true, false);
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
nlwarning("Error while setting search path");
|
|
}
|
|
|
|
|
|
loadDlg.Message = "Initializing Audio Mixer";
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.RedrawWindow();
|
|
// init the mixer
|
|
_Mixer = UAudioMixer::createAudioMixer();
|
|
// the the sample path
|
|
_Mixer->setSamplePath(cf.getVar("SamplePath").asString());
|
|
_Mixer->setPackedSheetOption(cf.getVar("PackedSheetPath").asString(), true);
|
|
// and init
|
|
_Mixer->init(32, true, false, NULL, true);
|
|
|
|
_Listener = _Mixer->getListener();
|
|
|
|
// load the sample banks.
|
|
/* try
|
|
{
|
|
_Mixer->setSamplePath(cf.getVar("sample_path").asString());
|
|
CConfigFile::CVar *psampleBanks = cf.getVarPtr("load_sample_bank");
|
|
if (psampleBanks != 0)
|
|
{
|
|
for (sint i=0; i<psampleBanks->size(); ++i)
|
|
{
|
|
loadDlg.Message = (string("Loading sample bank \"")+psampleBanks->asString(i)+"\"").c_str();
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.RedrawWindow();
|
|
_Mixer->loadSampleBank(false, psampleBanks->asString(i));
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
nlwarning("Error while loading sample banks");
|
|
}
|
|
*/
|
|
// load the sound banks.
|
|
/* try
|
|
{
|
|
CConfigFile::CVar *psoundBanks = cf.getVarPtr("load_sound_bank");
|
|
if (psoundBanks != 0)
|
|
{
|
|
for (sint i=0; i<psoundBanks->size(); ++i)
|
|
{
|
|
loadDlg.Message = (string("Loading sound bank \"")+psoundBanks->asString(i)+"\"").c_str();
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.RedrawWindow();
|
|
// _Mixer->loadSoundBank(psoundBanks->asString(i));
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
nlwarning("Error while loading sound banks");
|
|
}
|
|
*/
|
|
// loadDlg.CloseWindow();
|
|
loadDlg.DestroyWindow();
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
CSoundPlugin::~CSoundPlugin ()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
stop();
|
|
|
|
_Dialog.DestroyWindow();
|
|
|
|
|
|
// _Dialog.ShowWindow(SW_HIDE);
|
|
// _Dialog.DestroyWindow();
|
|
|
|
/* if (_Buffer != 0)
|
|
{
|
|
delete _Buffer;
|
|
}
|
|
|
|
*/ if (_Sound != 0 && _FreeSound)
|
|
{
|
|
delete _Sound;
|
|
}
|
|
|
|
delete _Mixer;
|
|
|
|
/*
|
|
if (_Listener != 0)
|
|
{
|
|
delete _Listener;
|
|
}
|
|
|
|
if (_SoundDriver != 0)
|
|
{
|
|
delete _SoundDriver;
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
bool CSoundPlugin::checkSound(CSound *sound, const vector<pair<string, CSound*> > &subsounds, vector<string> &missingFiles)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
vector<pair<string, CSound*> >::const_iterator first(subsounds.begin()), last(subsounds.end());
|
|
|
|
for (; first != last; ++first)
|
|
{
|
|
if (first->second == sound)
|
|
return false;
|
|
|
|
if (first->second == 0 && !first->first.empty())
|
|
missingFiles.push_back(first->first);
|
|
else if (first->second != 0)
|
|
{
|
|
vector<pair<string, CSound*> > v2;
|
|
first->second->getSubSoundList(v2);
|
|
|
|
if (!checkSound(sound, v2, missingFiles))
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::dialogInit(HWND mainFrm)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Initilize the search path for CPath::lookup
|
|
string searchPath;
|
|
_GlobalInterface->getSearchPath(searchPath);
|
|
CPath::addSearchPath(searchPath, true, true);
|
|
|
|
_Dialog.init(this, mainFrm);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
bool CSoundPlugin::pretranslateMessage(MSG *pMsg)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_SPACE))
|
|
{
|
|
//MessageBox (NULL, "PLAY!", "Sound plugin", MB_OK);
|
|
|
|
// if (_Source)
|
|
// {
|
|
// if (!_Source->isPlaying())
|
|
// {
|
|
play();
|
|
/* }
|
|
else
|
|
{
|
|
stop();
|
|
play();
|
|
}
|
|
*/// }
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CSoundPlugin::hasAlpha()
|
|
{
|
|
if (_Sound)
|
|
return _Sound->getSoundType() == CSound::SOUND_SIMPLE;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
void CSoundPlugin::updateDisplay()
|
|
{
|
|
if (_Sound != 0)
|
|
{
|
|
if (_Sound->getSoundType() == CSound::SOUND_SIMPLE)
|
|
{
|
|
CSimpleSound *ss = static_cast<CSimpleSound*>(_Sound);
|
|
setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance());
|
|
_Dialog.setAlpha(static_cast<CSimpleSound*>(_Sound)->getAlpha());
|
|
}
|
|
else
|
|
{
|
|
setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m to max dist.
|
|
}
|
|
_Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSoundPlugin::setActiveDocument(IEditDocument *pdoc)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
stop();
|
|
if (_Source != NULL)
|
|
{
|
|
// _Mixer->removeSource(_Source);
|
|
delete _Source;
|
|
_Source = NULL;
|
|
}
|
|
// release old sound.
|
|
if (_Sound != NULL && _FreeSound)
|
|
{
|
|
delete _Sound;
|
|
_Sound = NULL;
|
|
}
|
|
if (_ActiveDoc != pdoc)
|
|
{
|
|
// we have changed document.
|
|
_InvalidSound = false;
|
|
}
|
|
|
|
_ActiveDoc = pdoc;
|
|
if (_ActiveDoc != NULL)
|
|
{
|
|
//std::string filename;
|
|
_ActiveDoc->getFilename(_Filename);
|
|
_Filename = NLMISC::CFile::getFilenameWithoutExtension(_Filename);
|
|
_Dialog.setName(_Filename);
|
|
|
|
// 1st, try to found the sound in the preloaded sound bank.
|
|
_Sound = _Mixer->getSoundId(CSheetId(_Filename, "sound"));
|
|
if (_Sound == NULL)
|
|
{
|
|
// not found, create a new one.
|
|
_Sound = CSound::createSound(_Filename, _ActiveDoc->getForm()->getRootNode());
|
|
_FreeSound = true;
|
|
}
|
|
else
|
|
{
|
|
// update the existing sound with the george document
|
|
_Sound->importForm(_Filename, _ActiveDoc->getForm()->getRootNode());
|
|
_FreeSound = false;
|
|
}
|
|
if (_Sound)
|
|
{
|
|
vector<pair<string, CSound*> > subsounds;
|
|
_Sound->getSubSoundList(subsounds);
|
|
vector<string> missingFiles;
|
|
bool invalid = !checkSound(_Sound, subsounds, missingFiles);
|
|
|
|
if (invalid && !_InvalidSound)
|
|
{
|
|
MessageBox(NULL, "This sound contains an infinite recursion !", "Sound Error", MB_ICONERROR);
|
|
}
|
|
|
|
// pre-create the sound to force loading any missing sample bank (thus avoiding unwanted message box)
|
|
_Dialog.fillContextArgs(&_Context);
|
|
_Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, NULL);
|
|
if (_Source)
|
|
delete _Source;
|
|
_Source = NULL;
|
|
|
|
// recheck the sound
|
|
missingFiles.clear();
|
|
subsounds.clear();
|
|
_Sound->getSubSoundList(subsounds);
|
|
invalid = !checkSound(_Sound, subsounds, missingFiles);
|
|
|
|
invalid |= !missingFiles.empty();
|
|
if (!missingFiles.empty() && !_InvalidSound)
|
|
{
|
|
/* // try to load missing sample bank
|
|
for (uint i=0; i<missingFiles.size(); ++i)
|
|
{
|
|
if (missingFiles[i].find(" (sample)") != string::npos)
|
|
{
|
|
// try to find the sample bank
|
|
string sample = missingFiles[i].substr(0, missingFiles[i].find(" (sample)")) + ".wav";
|
|
string path = CPath::lookup(sample, false, false, false);
|
|
if (!path.empty())
|
|
{
|
|
// extract samplebank name
|
|
path = NLMISC::CFile::getPath(path);
|
|
vector<string> rep;
|
|
explode(path, "/", rep, true);
|
|
|
|
_Mixer->loadSampleBank(false, rep.back());
|
|
|
|
goto retrySound;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
string message("The folowing files are missing for this sound :\n");
|
|
vector<string>::iterator first(missingFiles.begin()), last(missingFiles.end());
|
|
for (;first != last;++first)
|
|
{
|
|
message += (*first)+"\n";
|
|
}
|
|
|
|
MessageBox(NULL, message.c_str(), "Sound incomplete", MB_ICONWARNING);
|
|
}
|
|
|
|
|
|
// NB : _InvalidSound and invalid are used to avoid repetitive warning message.
|
|
// After a first warning message, the message masked until the sound become
|
|
// valid (ie : no recursion in sound dependance and no missing files).
|
|
_InvalidSound = invalid;
|
|
|
|
|
|
std::string filename;
|
|
_ActiveDoc->getFilename(filename);
|
|
_Dialog.setFilename(filename);
|
|
_Dialog.fillContextArgs(&_Context);
|
|
_Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context);
|
|
|
|
if (_Sound->getSoundType() == CSound::SOUND_SIMPLE)
|
|
{
|
|
CSimpleSound *ss = static_cast<CSimpleSound*>(_Sound);
|
|
setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance());
|
|
}
|
|
else
|
|
{
|
|
setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m to max dist.
|
|
}
|
|
_Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi));
|
|
if (!_InvalidSound)
|
|
_Dialog.setDuration(_Sound->getDuration());
|
|
else
|
|
_Dialog.setDuration(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSoundPlugin::updateEnvFlags(const UAudioMixer::TBackgroundFlags &backgroundFlags)
|
|
{
|
|
_Mixer->setBackgroundFlags(backgroundFlags);
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::onCreateDocument(IEditDocument *document)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Set text in the global dialog
|
|
string dfn;
|
|
document->getDfnFilename(dfn);
|
|
|
|
// Bind an interface on the document
|
|
if (dfn.compare("sound.dfn") == 0)
|
|
{
|
|
document->bind(this, new CSoundDocumentPlugin(this, document));
|
|
}
|
|
|
|
stop();
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::createNew()
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
char BASED_CODE szFilter[] = "Sound (*.sound)|*.sound|All Files (*.*)|*.*||";
|
|
CFileDialog fileDlg(FALSE, ".sound", "*.sound", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter);
|
|
|
|
if (fileDlg.DoModal() == IDOK)
|
|
{
|
|
string filename = (const char*) fileDlg.GetPathName();
|
|
_GlobalInterface->createDocument("sound.dfn", filename.c_str());
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::activate(bool activate)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if (IsWindow(_Dialog))
|
|
{
|
|
_Dialog.ShowWindow(activate? SW_SHOW : SW_HIDE);
|
|
}
|
|
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::getPluginName(std::string &name)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
name = "Sound plugin";
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::play(std::string &filename)
|
|
{
|
|
try
|
|
{
|
|
stop();
|
|
// force to recreate the sound (mainly for contextual sound)
|
|
setActiveDocument(_ActiveDoc);
|
|
|
|
if (_Sound != NULL && !_InvalidSound)
|
|
{
|
|
// if it is a context source, recreate the source each time
|
|
if( _Sound->getSoundType() == CSound::SOUND_CONTEXT)
|
|
{
|
|
if (_Source != NULL)
|
|
// _Mixer->removeSource(_Source);
|
|
delete _Source;
|
|
_Dialog.fillContextArgs(&_Context);
|
|
_Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context);
|
|
}
|
|
|
|
if (_Sound->getSoundType() == CSound::SOUND_BACKGROUND)
|
|
{
|
|
// this is a background sound, we must create a pseudo environnent for baground sound
|
|
NLLIGO::CPrimRegion region;
|
|
|
|
region.Name = "simulation";
|
|
|
|
NLLIGO::CPrimPoint point;
|
|
point.Point = NLMISC::CVector::Null;
|
|
// point.Name = string("simulation-")+_Sound->getName()+"-000";
|
|
|
|
region.VPoints.push_back(point);
|
|
string name = string("simulation-")+NLMISC::CFile::getFilenameWithoutExtension(_Sound->getName().toString())+"-000";
|
|
if (region.VPoints.back().checkProperty("name"))
|
|
region.VPoints.back().removePropertyByName("name");
|
|
|
|
region.VPoints.back().addPropertyByName("name", new NLLIGO::CPropertyString(name));
|
|
|
|
|
|
// TODO : repair this
|
|
// _Mixer->loadBackgroundSoundFromRegion(region);
|
|
_Mixer->setBackgroundFilterFades(_Dialog.FilterFades);
|
|
_Mixer->playBackgroundSound();
|
|
_Mixer->setBackgroundFilterFades(_Dialog.FilterFades);
|
|
_PlayBackground = true;
|
|
}
|
|
else if (_Source)
|
|
{
|
|
_Source->setPos (CVector(0,0,0));
|
|
_Source->play();
|
|
_Dialog.setPlaying(true);
|
|
}
|
|
}
|
|
|
|
/* if (_Buffer != 0)
|
|
{
|
|
_Source->setStaticBuffer(0);
|
|
delete _Buffer;
|
|
_Buffer = 0;
|
|
}
|
|
|
|
if (filename.empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
_Buffer = _SoundDriver->createBuffer();
|
|
|
|
string path = CPath::lookup(filename, true, true, true);
|
|
_SoundDriver->loadWavFile(_Buffer, path.c_str());
|
|
|
|
_Source->setStaticBuffer(_Buffer);
|
|
_Source->play();
|
|
*/
|
|
}
|
|
catch (ESoundDriver& e)
|
|
{
|
|
string reason = e.what();
|
|
MessageBox (NULL, reason.c_str(), "Sound plugin", MB_OK);
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void CSoundPlugin::stop()
|
|
{
|
|
if (_Sound && _Sound->getSoundType() == CSound::SOUND_BACKGROUND)
|
|
{
|
|
_Mixer->stopBackgroundSound();
|
|
_PlayBackground = false;
|
|
}
|
|
else if (_Source)
|
|
{
|
|
if (_Source->isPlaying())
|
|
{
|
|
_Dialog.setPlaying(false);
|
|
_Source->stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
uint32 CSoundPlugin::getTime()
|
|
{
|
|
if ((_Source == 0) /*|| !_Source->isPlaying()*/)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return _Source->getTime();
|
|
}
|
|
}
|
|
|
|
void CSoundPlugin::update()
|
|
{
|
|
_Mixer->update();
|
|
}
|
|
|
|
bool CSoundPlugin::isPlaying()
|
|
{
|
|
if (_Sound && _Sound->getSoundType() == NLSOUND::CSound::SOUND_BACKGROUND)
|
|
return _PlayBackground;
|
|
else if (_Source)
|
|
return _Source->isPlaying();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
void CSoundPlugin::reloadSamples()
|
|
{
|
|
/* CLoadingDialog loadDlg;
|
|
loadDlg.Create(IDD_DIALOG_LOADING);
|
|
loadDlg.Message = "Reloading sample banks...";
|
|
loadDlg.UpdateData(FALSE);
|
|
loadDlg.ShowWindow(SW_SHOW);
|
|
*/
|
|
_Mixer->reloadSampleBanks(false);
|
|
|
|
// loadDlg.CloseWindow();
|
|
// loadDlg.DestroyWindow();
|
|
}
|
|
|
|
void CSoundPlugin::reloadSounds()
|
|
{
|
|
// _Mixer->reloadSounds();
|
|
}
|
|
|
|
|
|
|
|
} // namespace NLGEORGES
|