cocos2dx win32下修改音量大小

来源:互联网 发布:xinnet域名管理 编辑:程序博客网 时间:2024/05/24 15:43
寫在前面,此方法不適合跨平台,純粹為實現win32平台下的音量修改。方法是用directshow,以前寫過一篇文章是說在遊戲中播放視頻的。

具體的方法如下:

1. 創建一個hidewindow,這也是simpleaudioengine的做法,用來處理directshow產生的事件

2. 初始化COM接口

3. 播放文件

4. 關閉接口

 

#define WIN32_LEAN_AND_MEAN#include <tchar.h>#include <stdio.h>#include <dshow.h>#include <atlbase.h>#include <strsafe.h>#include "CCDirector.h"#include "movieplay.h"#include <Windows.h>//// Globals//NS_CC_BEGINIGraphBuilder  *pGB = NULL;IMediaControl  *pMC = NULL;IVideoWindow   *pVW = NULL;IMediaEventEx  *pME = NULL;IBasicAudio    *pBA = NULL;IMediaSeeking  *pMS = NULL;IMediaPosition *pMP = NULL;BOOL g_bContinue=FALSE, g_bUserInterruptedPlayback=FALSE;static HWND g_sndHWND;static HINSTANCE s_hInstance;static HWND g_videoHWND;//// Function prototypes//#define RELEASE(i) {if (i) i->Release(); i = NULL;}HRESULT PlaySoundMedia(LPTSTR lpszSound,HWND hwnd);HRESULT GetInterfaces(HWND);void SoundHandleEvent();void CreateHideWindow();LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

HRESULT GetInterfaces(HWND hwnd){HRESULT hr = S_OK;// Instantiate filter graph interfaceCoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB);// Get interfaces to control playback & screensizepGB->QueryInterface(IID_IMediaControl,  (void **)&pMC);pGB->QueryInterface(IID_IVideoWindow,   (void **)&pVW);pGB->QueryInterface(IID_IMediaSeeking,  (void **)&pMS);pGB->QueryInterface(IID_IMediaPosition,  (void **)&pMP);// Get interface to allow the app to wait for completion of playbackpGB->QueryInterface(IID_IMediaEventEx,  (void **)&pME);// For audiopGB->QueryInterface(IID_IBasicAudio, (void **)&pBA);/*// Set windows positionpVW->put_Owner((OAHWND)hwnd);pVW->put_WindowStyle(WS_CLIPSIBLINGS | WS_CHILD);RECT grc;GetClientRect(hwnd, &grc);pVW->SetWindowPosition(grc.left, grc.top, grc.right, grc.bottom);*/return S_OK;// In case of failure, the helper macro jumps here}void CleanupInterfaces(){// Release the DirectShow interfaces//cocos2d::CCDirector::sharedDirector()->startAnimation();if (pME)pME->SetNotifyWindow(NULL,0,0);// Stop playback and exitif (pMC)pMC->Stop();RELEASE(pGB);RELEASE(pMC);RELEASE(pVW);RELEASE(pME);RELEASE(pMS);RELEASE(pBA);RELEASE(pMP);CoUninitialize();}


 

HRESULT GetInterfaces(HWND hwnd){HRESULT hr = S_OK;// Instantiate filter graph interfaceCoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB);// Get interfaces to control playback & screensizepGB->QueryInterface(IID_IMediaControl,  (void **)&pMC);pGB->QueryInterface(IID_IVideoWindow,   (void **)&pVW);pGB->QueryInterface(IID_IMediaSeeking,  (void **)&pMS);pGB->QueryInterface(IID_IMediaPosition,  (void **)&pMP);// Get interface to allow the app to wait for completion of playbackpGB->QueryInterface(IID_IMediaEventEx,  (void **)&pME);// For audiopGB->QueryInterface(IID_IBasicAudio, (void **)&pBA);/*// Set windows positionpVW->put_Owner((OAHWND)hwnd);pVW->put_WindowStyle(WS_CLIPSIBLINGS | WS_CHILD);RECT grc;GetClientRect(hwnd, &grc);pVW->SetWindowPosition(grc.left, grc.top, grc.right, grc.bottom);*/return S_OK;// In case of failure, the helper macro jumps here}void CleanupInterfaces(){// Release the DirectShow interfaces//cocos2d::CCDirector::sharedDirector()->startAnimation();if (pME)pME->SetNotifyWindow(NULL,0,0);// Stop playback and exitif (pMC)pMC->Stop();RELEASE(pGB);RELEASE(pMC);RELEASE(pVW);RELEASE(pME);RELEASE(pMS);RELEASE(pBA);RELEASE(pMP);CoUninitialize();}

 
HRESULT PlaySoundFile(LPTSTR szSound, bool bLoop) {g_bContinue = bLoop;CreateHideWindow();CloseSound();if (!szSound)return E_POINTER;HRESULT hr;// Create the main hidden window to field keyboard input//if (!CreateHiddenWindow(hInstance, szMovie))//return E_FAIL;// Initialize COMif (FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))return hr;// Get DirectShow interfacesif (FAILED(hr = GetInterfaces(g_sndHWND))){CoUninitialize();return hr;}pME->SetNotifyWindow((OAHWND)g_sndHWND,WM_SOUNDEVENT,0);// Play the movie / cutscenePlaySoundMedia(szSound,g_sndHWND);// If the user interrupted playback and there was no other error,// return S_FALSE.if ((hr == S_OK) && g_bUserInterruptedPlayback)hr = S_FALSE;// Release DirectShow interfaces//CleanupInterfaces();//CoUninitialize();return hr;}double GetSoundTime() {double duration;if (pMP)pMP->get_Duration(&duration);return duration;}void PauseSound() {pMC->Pause();}void StopSound() {pMC->Stop();}void ResumeSound() {pMC->Run();}void CloseSound() {if (pME)pME->SetNotifyWindow((OAHWND)NULL,0,0);// Stop playback and exitif (pMC)pMC->Stop();RELEASE(pGB);RELEASE(pMC);RELEASE(pVW);RELEASE(pME);RELEASE(pMS);RELEASE(pBA);RELEASE(pMP);CoUninitialize();}void GetSoundVolume(long g_lVolume) {    pBA->get_Volume(&g_lVolume);}void SetSoundVolume(long lVol) {pBA->put_Volume(lVol);}void SetMuteVolume() {SetSoundVolume(-10000);}void SetFullVolume() {SetSoundVolume(0);}bool IsSoundPlaying() {bool result;long lEventCode;LONG_PTR lpParam1, lpParam2;HRESULT hr = pME->GetEvent(&lEventCode, &lpParam1, &lpParam2, 0);if (lEventCode == EC_ACTIVATE)if (lpParam1 == TRUE)result = TRUE;elseresult = FALSE;return result;}bool IsSoundStop() {return !IsSoundPlaying();}void SoundHandleEvent() {HRESULT hr = S_OK;//g_bContinue = TRUE;MSG msg;long lEventCode;LONG_PTR lpParam1, lpParam2;// Enter a loop of checking for events and sampling keyboard inputwhile (hr = pME->GetEvent(&lEventCode, &lpParam1, &lpParam2, 0),SUCCEEDED(hr)) {hr = pME->FreeEventParams(lEventCode, lpParam1, lpParam2);if (g_bContinue == TRUE) {if(EC_COMPLETE == lEventCode) {LONGLONG pos = 0;hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);pMC->Pause();pMC->Run();} else if (lEventCode == EC_WINDOW_DESTROYED || lEventCode == EC_USERABORT) {CloseSound();break;}} else {if (lEventCode == EC_COMPLETE || lEventCode == EC_WINDOW_DESTROYED || lEventCode == EC_USERABORT) {CloseSound();break;}}}}HRESULT PlaySoundMedia(LPTSTR lpszSound,HWND hwnd) {USES_CONVERSION;WCHAR wFileName[MAX_PATH];BOOL bSleep=TRUE;HRESULT hr = S_OK;if (!lpszSound)return E_POINTER;wcsncpy(wFileName, T2W(lpszSound), MAX_PATH-1);wFileName[MAX_PATH - 1] = 0;hr = pGB->RenderFile(wFileName, NULL);// Display first frame of the moviehr = pMC->Pause();// Start playbackhr = pMC->Run();}void CreateHideWindow() {if (! s_hInstance) {s_hInstance = GetModuleHandle( NULL );            // Grab An Instance For Our WindowWNDCLASS  wc;        // Windows Class Structure// Redraw On Size, And Own DC For Window.wc.style          = 0;  wc.lpfnWndProc    = _SoundPlayProc;                    // WndProc Handles Messageswc.cbClsExtra     = 0;                              // No Extra Window Datawc.cbWndExtra     = 0;                                // No Extra Window Datawc.hInstance      = s_hInstance;                    // Set The Instancewc.hIcon          = 0;                                // Load The Default Iconwc.hCursor        = LoadCursor( NULL, IDC_ARROW );    // Load The Arrow Pointerwc.hbrBackground  = NULL;                           // No Background Required For GLwc.lpszMenuName   = NULL;                           // We Don't Want A Menuwc.lpszClassName  = TEXT("Sound Play");                 // Set The Class Nameif (! RegisterClass(&wc)&& 1410 != GetLastError()){return;}}g_sndHWND = CreateWindowEx(WS_EX_APPWINDOW,                                    // Extended Style For The WindowTEXT("Sound Play"),                                        // Class NameNULL,                                        // Window TitleWS_POPUPWINDOW,/*WS_OVERLAPPEDWINDOW*/               // Defined Window Style0, 0,                                                // Window Position0,                                                    // Window Width0,                                                    // Window HeightNULL,                                                // No Parent WindowNULL,                                                // No Menus_hInstance,                                        // InstanceNULL );if (g_sndHWND){;//SetWindowLong(g_sndHWND, GWL_USERDATA, (LONG)wc);}}LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {switch(Msg) {case WM_SOUNDEVENT:SoundHandleEvent();break;}return DefWindowProc(hWnd, Msg, wParam, lParam);}NS_CC_END


注:通過directshow獲得的當前音量大小為0,即使重新改過了也是0。

下面看看一個效果,隨著場景的談出,也讓音樂同時談出。

 

void CastScene::onExitTransitionDidStart() {PVZDebugLog("CastScene Transition Exit");this->schedule(schedule_selector(CastScene::updateMusicFadeout),0.5f);}void CastScene::replaceWithMainScene() {// CCScene* scene = new CCScene();// CCLayer* pLayer = new MainMenuScene();// pLayer->autorelease();// scene->addChild(pLayer, 0);//  For transition without effect, mustbe autorelease for eachlayer//CCSprite *pSpr = (CCSprite*)this->getChildByTag(LAYER_TAG::tagLabel);//this->removeChildByTag(LAYER_TAG::tagLabel);this->unschedule(schedule_selector(CastScene::updateKeyboardSelect));CCScene *s = new TransitionCastScenePage();CCLayer* pLayer = new CastScenePlaceholder();s->addChild(pLayer);CCScene* pScene = CCTransitionFade::create(3.0f,s);if (pScene) {//CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic(true);    CCDirector::sharedDirector()->replaceScene(pScene);}s->release();pLayer->release();}


 

void CastScene::updateMusicFadeout(float dt) {g_lVol -= 500;SetSoundVolume(g_lVol);//CocosDenshion::SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();}


 

g_lVol為此編譯單元中的全局變量,在init()中設置為0。