// Ryzom - MMORPG Framework // 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 . #include "std_sound_plugin.h" #include "PageComplex.h" #include "PageComtext.h" #include "PageBgFlags.h" #include "PageBgFades.h" #include "PageSimple.h" #include "PagePosition.h" #include "sound_dialog.h" #include "listener_view.h" #include "sound_document_plugin.h" #include "resource.h" #include "nel/misc/debug.h" #include "nel/misc/path.h" #include "nel/georges/u_form_elm.h" #include #include using namespace std; using namespace NLMISC; namespace NLGEORGES { CBitmap CSoundDialog::_StopBitmap; CBitmap CSoundDialog::_StartBitmap; CBitmap CSoundDialog::_DesactivatedBitmap; CBitmap CSoundDialog::_NewBitmap; CBitmap CSoundDialog::_ContextBitmap; CPen CSoundDialog::_Red; BEGIN_MESSAGE_MAP(CSoundDialog, CDialog) //{{AFX_MSG_MAP(CSoundDialog) ON_WM_TIMER() ON_WM_KEYUP() ON_BN_CLICKED(IDC_CONTROL, OnControlPlayback) ON_NOTIFY(UDN_DELTAPOS, IDC_ZOOM, OnZoom) ON_BN_CLICKED(IDC_BUTTON_RELOAD_SAMPLES, OnReloadSamples) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() CSoundDialog::CSoundDialog() : CDialog(), _Plugin(0), _Playing(false), _Timer(0), _PagePosition(0), _PageSimple(0), _PageComplex(0), _PageComtext(0), _PageBgFlags(0) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); //{{AFX_DATA_INIT(CSoundDialog) //}}AFX_DATA_INIT } // *************************************************************************** CSoundDialog::~CSoundDialog() { } // *************************************************************************** void CSoundDialog::init(CSoundPlugin* plugin, HWND documentView) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); _Plugin = plugin; if (HBITMAP(_StopBitmap) == 0) { _StopBitmap.LoadBitmap(IDB_STOP); _StartBitmap.LoadBitmap(IDB_START); _DesactivatedBitmap.LoadBitmap(IDB_DESACTIVATED); _NewBitmap.LoadBitmap(IDB_NEW); _ContextBitmap.LoadBitmap(IDB_CONTEXT); _Red.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); } _OuterAngle = 360; _InnerAngle = 360; Create(IDD_TEST_LOCAL, CWnd::FromHandle(documentView)); NLSOUND::UAudioMixer *mixer = _Plugin->getMixer(); // set the name an fade FilterFades = mixer->getBackgroundFilterFades(); _BackgroundFlags = mixer->getBackgroundFlags(); for (uint i=0; igetBackgroundFlagName(i); envName.ShortName = mixer->getBackgroundFlagShortName(i); EnvNames.push_back(envName); } // CConfigFile &cf = _Plugin->getGlobalInterface()->getConfigFile(); /* try { CConfigFile::CVar *penvNames = cf.getVarPtr("background_sound_environment"); EnvNames.clear(); sint i; for (i=0; i< min(penvNames->size() / 4, 32); ++i) { TEnvName envName; envName.Name = penvNames->asString(i*4); envName.ShortName = penvNames->asString(i*4+1); FilterFades.FadeIns[i] = penvNames->asInt(i*4+2); FilterFades.FadeOuts[i] = penvNames->asInt(i*4+3); EnvNames.push_back(envName); } for (; i < 32; ++i) { TEnvName envName; char tmp[50]; sprintf(tmp, "Filter %02u", i); envName.Name = tmp; sprintf(tmp, "%02u", i); envName.ShortName = tmp; EnvNames.push_back(envName); } } catch(...) { } */ return; CRect rect(0,0,200,200); #undef new CWnd *wnd = new CWnd(); #define new NL_NEW } void CSoundDialog::DoDataExchange(CDataExchange *pDX) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); //{{AFX_DATA_MAP(CSoundDialog) DDX_Control(pDX, IDC_SHEET_POS, _SheetPos); //}}AFX_DATA_MAP } // *************************************************************************** void CSoundDialog::setPlaying(bool play) { _Playing = play; updateButton(); } // *************************************************************************** // *************************************************************************** void CSoundDialog::OnTimer(UINT_PTR id) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); updateTime(); } // *************************************************************************** void CSoundDialog::OnZoom(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; } // *************************************************************************** void CSoundDialog::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if ((nChar == VK_SPACE) && _Plugin->isSoundValid()) { // _Plugin->play(_Filename); OnControlPlayback(); } } // *************************************************************************** void CSoundDialog::updateTime() { _Plugin->update(); uint32 msec = _Plugin->getTime(); // if (msec == 0) if (!_Plugin->isPlaying()) { setPlaying(false); return; } displayTime(msec); } // *************************************************************************** void CSoundDialog::displayTime(uint32 msec) { char s[256]; uint sec = msec / 1000; uint min = sec / 60; sec -= min * 60; _snprintf(s, 256, "%02d:%02d", min, sec); GetDlgItem(IDC_TIME)->SetWindowText(s); } // *************************************************************************** void CSoundDialog::updateButton() { CButton* control = (CButton*) GetDlgItem(IDC_CONTROL); // if (_Filename.empty()) if (!_Plugin->isSoundValid()) { control->SetBitmap(_DesactivatedBitmap); control->SetCheck(0); } else { if (_Playing) { control->SetBitmap(_StopBitmap); control->SetCheck(1); } else { control->SetBitmap(_StartBitmap); control->SetCheck(0); } } } void CSoundDialog::setDuration(uint32 msec) { _Duration = msec; updateInfo(); } // *************************************************************************** void CSoundDialog::updateInfo() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CPageBase::docChanged(); SetWindowText(_Name.c_str()); char s[256]; /* if (_Filename.empty()) { SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); SetWindowText("[no file selected]"); GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); GetDlgItem(IDC_FILENAME)->SetWindowText("[no file selected]"); GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); GetDlgItem(IDC_FILESIZE)->SetWindowText(""); // GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); } else { uint sampleRate, sampleSize, channels, size; if (getFileInfo(_Filename, sampleRate, sampleSize, channels, size)) { if (channels > 1) { ::MessageBox(NULL, "3D sounds accept only mono files", _Name.c_str(), MB_OK); } GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); GetDlgItem(IDC_FILENAME)->SetWindowText(_Filename.c_str()); _snprintf(s, 256, "%s / %d bits / %d Hz", (channels == 1)? "mono" : "stereo", sampleSize, sampleRate); GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(s); _snprintf(s, 256, "%d kb", size / 1024); GetDlgItem(IDC_FILESIZE)->SetWindowText(s); // uint msec = 1000 * size / sampleRate; } else { _Filename.erase(); SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); GetDlgItem(IDC_FILENAME)->SetWindowText("[invalid file]"); GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); GetDlgItem(IDC_FILESIZE)->SetWindowText(""); // GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); } } */ // the duration is always valid. uint msec = _Duration; uint sec = msec / 1000; uint min = sec / 60; msec -= sec * 1000; sec -= min * 60; _snprintf(s, 256, "%02d:%02d.%03d", min, sec, msec); GetDlgItem(IDC_DURATION)->SetWindowText(s); updateButton(); } // *************************************************************************** bool CSoundDialog::getFileInfo(string& filename, uint& sampleRate, uint& sampleSize, uint& channels, uint& size) { // Try to find the absolute path of the file string path = CPath::lookup(filename, false, false, true); if (path.empty()) { // If we failed try to open the file as a local file anyway path = filename; } // Open the file HMMIO hmmio = mmioOpen((char*) path.c_str(), NULL, MMIO_READ | MMIO_DENYWRITE); if (hmmio == NULL) { return false; } // Check it's a WAVE file MMCKINFO riff_chunk; sint error = (sint) mmioDescend(hmmio, &riff_chunk, NULL, 0); if ((error != 0) || (riff_chunk.ckid != FOURCC_RIFF) || (riff_chunk.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) { mmioClose(hmmio, 0); return false; } // Search the format chunk MMCKINFO chunk; chunk.ckid = mmioFOURCC('f', 'm', 't', ' '); error = (sint) mmioDescend(hmmio, &chunk, &riff_chunk, MMIO_FINDCHUNK); if (error != 0) { mmioClose(hmmio, 0); return false; } if (chunk.cksize < (long) sizeof(PCMWAVEFORMAT)) { mmioClose(hmmio, 0); return false; } // read in the format data WAVEFORMATEX format; sint num = mmioRead(hmmio, (HPSTR) &format, (long) sizeof(format)); if (num != (long) sizeof(format)) { mmioClose(hmmio, 0); return false; } format.cbSize = 0; // Get out of the format chunk if (mmioAscend(hmmio, &chunk, 0) != 0) { mmioClose(hmmio, 0); return false; } // Copy the format data if (format.wFormatTag != WAVE_FORMAT_PCM) { mmioClose(hmmio, 0); return false; } sampleRate = format.nSamplesPerSec; channels = format.nChannels; sampleSize = format.wBitsPerSample; // Set the file position to the beginning of the data chunk sint32 pos = mmioSeek(hmmio, riff_chunk.dwDataOffset + sizeof(FOURCC), SEEK_SET); if (pos < 0) { mmioClose(hmmio, 0); return false; } // Read the data chunk MMCKINFO data_chunk; data_chunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hmmio, &data_chunk, &riff_chunk, MMIO_FINDCHUNK) != 0) { mmioClose(hmmio, 0); return false; } // Copy the size size = data_chunk.cksize; // We're done mmioClose(hmmio, 0); return true; } // *************************************************************************** void CSoundDialog::updateAngles() { // _ListenerView->setActive(!_Filename.empty()); /* _ListenerView->setActive(true); _ListenerView->setShowAlpha(_Plugin->hasAlpha()); _ListenerView->setAngles(_InnerAngle, _OuterAngle); */ } void CSoundDialog::fillContextArgs(NLSOUND::CSoundContext *context) { if (_PageComtext != 0) { for (uint i =0; iArgs[i] = _PageComtext->SoundContext.Args[i]; } } // *************************************************************************** void CSoundDialog::OnControlPlayback() { if (!_Playing) { // check filename string str = NLMISC::CFile::getFilename(_Filename); if (str == "*.sound") { MessageBox("You must save the file before playing it !", "Warning"); return; } } setPlaying(!_Playing); if (_Playing) { _Plugin->play(_Filename); } else { _Plugin->stop(); } } void CSoundDialog::OnReloadSamples() { _Plugin->reloadSamples(); } BOOL CSoundDialog::OnInitDialog() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDialog::OnInitDialog(); WINDOWPLACEMENT place; _SheetPos.GetWindowPlacement(&place); // create the property sheet #undef new CPropertySheet *sheet = new CPropertySheet(); // create the property page... _PagePosition = new CPagePosition(this); _PageSimple = new CPageSimple(this); _PageComplex = new CPageComplex(this); _PageComtext = new CPageComtext(this); _PageBgFlags = new CPageBgFlags(this); _PageBgFades = new CPageBgFades(this); #define new NL_NEW sheet->AddPage(_PagePosition); sheet->AddPage(_PageSimple); sheet->AddPage(_PageComplex); sheet->AddPage(_PageComtext); sheet->AddPage(_PageBgFlags); sheet->AddPage(_PageBgFades); sheet->Create(this, WS_CHILD | WS_VISIBLE); // very important : the folowing two style ensure not entering into an infinite loop ! sheet->ModifyStyleEx (0, WS_EX_CONTROLPARENT); // sheet->ModifyStyle( 0, WS_TABSTOP ); // place the property sheet onver the picture sheet->SetWindowPos(NULL, place.rcNormalPosition.left, place.rcNormalPosition.top, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER); sheet->ShowWindow(TRUE); // start the timer for mixer update _Timer = SetTimer(1, 3, 0); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CSoundDialog::OnDestroy() { CDialog::OnDestroy(); KillTimer(_Timer); delete _PagePosition; delete _PageSimple; delete _PageComplex; delete _PageComtext; delete _PageBgFlags; delete _PageBgFades; _PagePosition = NULL; _PageSimple = NULL; _PageComplex = NULL; _PageComtext = NULL; _PageBgFlags = NULL; _PageBgFades = NULL; } } // namespace NLGEORGES