// translate string form of CLSID into binary form; tries Ole1Class too. // errors: E_INVALIDARG, CO_E_CLASSSTRING, REGDB_E_WRITEREGDB STDAPI SHCLSIDFromString(LPCTSTR lpsz, LPCLSID lpclsid) { if (lpsz == NULL) { *lpclsid = CLSID_NULL; return NOERROR; } return GUIDFromString(lpsz,lpclsid) ? NOERROR : ResultFromScode(CO_E_CLASSSTRING); }
//+--------------------------------------------------------------------------- // // Function: CLSIDFromString, Remote // // History: Straight from OLE2 sources // //---------------------------------------------------------------------------- STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid) { HRESULT hr; thkDebugOut((DEB_ITRACE, "CLSIDFromString\n")); // // The 16-bit OLE2 application "Family Tree Maker" always passes a bad // string to CLSIDFromString. We need to make sure we fail in the exact // same way with the interop layer. This will also provide a speed // improvement since we only need to remote to the 32bit version of // CLSIDFromString when the string provided does not start with '{'. // if (lpsz[0] == '{') return GUIDFromString(lpsz, pclsid) ? NOERROR : ResultFromScode(CO_E_CLASSSTRING); // Note: Corel calls this function prior to calling // CoInitialize so use CheckInit return (HRESULT)CallObjectInWOWCheckInit(THK_API_METHOD(THK_API_CLSIDFromString), PASCAL_STACK_PTR(lpsz)); }
BOOL CALLBACK DSound51::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { int wmId,wmEvent; int tSel=0; switch(uMsg) { case WM_INITDIALOG: haveGuid = ! FAILED(GUIDFromString(Config_DSound51.Device,&DevGuid)); SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0); ndevs=0; DirectSoundEnumerate(DSEnumCallback,NULL); tSel=-1; for(int i=0;i<ndevs;i++) { SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_ADDSTRING,0,(LPARAM)devices[i].name); if(haveGuid && IsEqualGUID(devices[i].guid,DevGuid)) { tSel=i; } } if(tSel>=0) { SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_SETCURSEL,tSel,0); } INIT_SLIDER(IDC_LEFT_GAIN_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_RIGHT_GAIN_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_RLEFT_GAIN_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_RRIGHT_GAIN_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_CENTER_GAIN_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_LFE_SLIDER,0,512,64,16,8); INIT_SLIDER(IDC_LR_CENTER_SLIDER,0,512,64,16,8); AssignSliderValue( hWnd, IDC_LEFT_GAIN_SLIDER, IDC_LEFT_GAIN_EDIT, Config_DSound51.GainL ); AssignSliderValue( hWnd, IDC_RIGHT_GAIN_SLIDER, IDC_RIGHT_GAIN_EDIT, Config_DSound51.GainR ); AssignSliderValue( hWnd, IDC_RLEFT_GAIN_SLIDER, IDC_RLEFT_GAIN_EDIT, Config_DSound51.GainSL ); AssignSliderValue( hWnd, IDC_RRIGHT_GAIN_SLIDER, IDC_RRIGHT_GAIN_EDIT, Config_DSound51.GainSR ); AssignSliderValue( hWnd, IDC_CENTER_GAIN_SLIDER, IDC_CENTER_GAIN_EDIT, Config_DSound51.GainC); AssignSliderValue( hWnd, IDC_LFE_SLIDER, IDC_LFE_EDIT, Config_DSound51.GainLFE); AssignSliderValue( hWnd, IDC_LR_CENTER_SLIDER, IDC_LR_CENTER_EDIT, Config_DSound51.AddCLR ); char temp[128]; INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 ); SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,Config_DSound51.NumBuffers); sprintf_s(temp, 128, "%d (%d ms latency)",Config_DSound51.NumBuffers, 1000 / (96000 / (Config_DSound51.NumBuffers * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL2),temp); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDOK: { int i = (int)SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_GETCURSEL,0,0); if(!devices[i].hasGuid) { Config_DSound51.Device[0]=0; // clear device name to "" } else { sprintf_s(Config_DSound51.Device,256,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", devices[i].guid.Data1, devices[i].guid.Data2, devices[i].guid.Data3, devices[i].guid.Data4[0], devices[i].guid.Data4[1], devices[i].guid.Data4[2], devices[i].guid.Data4[3], devices[i].guid.Data4[4], devices[i].guid.Data4[5], devices[i].guid.Data4[6], devices[i].guid.Data4[7] ); Config_DSound51.NumBuffers = GetSliderValue( hWnd, IDC_BUFFERS_SLIDER ); Config_DSound51.GainL = GetSliderValue( hWnd, IDC_LEFT_GAIN_SLIDER ); Config_DSound51.GainR = GetSliderValue( hWnd, IDC_RIGHT_GAIN_SLIDER ); Config_DSound51.GainSL = GetSliderValue( hWnd, IDC_RLEFT_GAIN_SLIDER ); Config_DSound51.GainSR = GetSliderValue( hWnd, IDC_RRIGHT_GAIN_SLIDER ); Config_DSound51.GainLFE = GetSliderValue( hWnd, IDC_LFE_SLIDER ); Config_DSound51.GainC = GetSliderValue( hWnd, IDC_CENTER_GAIN_SLIDER ); Config_DSound51.AddCLR = GetSliderValue( hWnd, IDC_LR_CENTER_SLIDER ); if( Config_DSound51.NumBuffers < 2 ) Config_DSound51.NumBuffers = 2; if( Config_DSound51.NumBuffers > MAX_BUFFER_COUNT ) Config_DSound51.NumBuffers = MAX_BUFFER_COUNT; } } EndDialog(hWnd,0); break; case IDCANCEL: EndDialog(hWnd,0); break; default: return FALSE; } break; case WM_HSCROLL: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch(wmId) { //case TB_ENDTRACK: //case TB_THUMBPOSITION: case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0); case TB_THUMBTRACK: if( wmEvent < 2 ) wmEvent = 2; if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT; SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent); sprintf_s(temp,128,"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL2),temp); break; default: return FALSE; } break; case WM_VSCROLL: HANDLE_SCROLL_MESSAGE(IDC_LEFT_GAIN_SLIDER,IDC_LEFT_GAIN_EDIT); HANDLE_SCROLL_MESSAGE(IDC_RIGHT_GAIN_SLIDER,IDC_RIGHT_GAIN_EDIT); HANDLE_SCROLL_MESSAGE(IDC_RLEFT_GAIN_SLIDER,IDC_RLEFT_GAIN_EDIT); HANDLE_SCROLL_MESSAGE(IDC_RRIGHT_GAIN_SLIDER,IDC_RRIGHT_GAIN_EDIT); HANDLE_SCROLL_MESSAGE(IDC_CENTER_GAIN_SLIDER,IDC_CENTER_GAIN_EDIT); HANDLE_SCROLL_MESSAGE(IDC_LFE_SLIDER,IDC_LFE_EDIT); HANDLE_SCROLL_MESSAGE(IDC_LR_CENTER_SLIDER,IDC_LR_CENTER_EDIT); default: return FALSE; } return TRUE; }
DSound51_Driver::DSound51_Driver( SndBuffer *sb ) : buff( sb ), numBuffers( Config_DSound51.NumBuffers ), dpl2( Config_DSound51.LowpassLFE, SampleRate ) { // // Initialize DSound // GUID cGuid; bool success = false; if( (strlen(Config_DSound51.Device)>0)&&(!FAILED(GUIDFromString(Config_DSound51.Device,&cGuid)))) { if( !FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) success = true; } // if the GUID failed, just open up the default dsound driver: if( !success ) { verifyc(DirectSoundCreate8(NULL,&dsound,NULL)); } verifyc(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.nSamplesPerSec = SampleRate; wfx.Format.nChannels=6; wfx.Format.wBitsPerSample = 16; wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8; wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign; wfx.Format.cbSize=22; wfx.Samples.wValidBitsPerSample=0; wfx.dwChannelMask=SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT; wfx.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; verifyc(dsound->SetSpeakerConfig(DSSPEAKER_5POINT1)); // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = DSound51::BufferSizeBytes * numBuffers; desc.lpwfxFormat = &wfx.Format; desc.dwFlags |=DSBCAPS_LOCSOFTWARE; desc.dwFlags|=DSBCAPS_GLOBALFOCUS; verifyc(dsound->CreateSoundBuffer(&desc,&buffer_,0)); verifyc(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)); buffer_->Release(); verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify)); DSBPOSITIONNOTIFY not[DSound51::MAX_BUFFER_COUNT]; for(u32 i=0;i<numBuffers;i++) { buffer_events[i]=CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset=(wfx.Format.nBlockAlign*2 + DSound51::BufferSizeBytes*(i+1))%desc.dwBufferBytes; not[i].hEventNotify=buffer_events[i]; } buffer_notify->SetNotificationPositions(numBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running=true; thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_TIME_CRITICAL); }
static BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { int wmId,wmEvent; int tSel=0; switch(uMsg) { case WM_INITDIALOG: { wchar_t temp[128]; char temp2[192]; sprintf_s( temp2, "%S", Config_DSoundOut.Device.c_str() ); haveGuid = ! FAILED(GUIDFromString(temp2,&DevGuid)); SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0); ndevs=0; DirectSoundEnumerate( DSEnumCallback, NULL ); tSel=-1; for(int i=0;i<ndevs;i++) { SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_ADDSTRING,0,(LPARAM)devices[i].name.c_str()); if(haveGuid && IsEqualGUID(devices[i].guid,DevGuid)) { tSel=i; } } if(tSel>=0) { SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_SETCURSEL,tSel,0); } INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 ); SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,Config_DSoundOut.NumBuffers); swprintf_s(temp, _T("%d (%d ms latency)"),Config_DSoundOut.NumBuffers, 1000 / (96000 / (Config_DSoundOut.NumBuffers * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp); } break; case WM_COMMAND: { wchar_t temp[128]; wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDOK: { int i = (int)SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_GETCURSEL,0,0); if(!devices[i].hasGuid) { Config_DSoundOut.Device[0] = 0; // clear device name to "" } else { swprintf_s(temp, _T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), devices[i].guid.Data1, devices[i].guid.Data2, devices[i].guid.Data3, devices[i].guid.Data4[0], devices[i].guid.Data4[1], devices[i].guid.Data4[2], devices[i].guid.Data4[3], devices[i].guid.Data4[4], devices[i].guid.Data4[5], devices[i].guid.Data4[6], devices[i].guid.Data4[7] ); Config_DSoundOut.Device = temp; } Config_DSoundOut.NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 ); if( Config_DSoundOut.NumBuffers < 2 ) Config_DSoundOut.NumBuffers = 2; if( Config_DSoundOut.NumBuffers > MAX_BUFFER_COUNT ) Config_DSoundOut.NumBuffers = MAX_BUFFER_COUNT; } EndDialog(hWnd,0); break; case IDCANCEL: EndDialog(hWnd,0); break; default: return FALSE; } } break; case WM_HSCROLL: { wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch(wmId) { //case TB_ENDTRACK: //case TB_THUMBPOSITION: case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0); case TB_THUMBTRACK: { wchar_t temp[128]; if( wmEvent < 2 ) wmEvent = 2; if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT; SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent); swprintf_s(temp,_T("%d (%d ms latency)"),wmEvent, 1000 / (96000 / (wmEvent * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp); break; } default: return FALSE; } } break; default: return FALSE; } return TRUE; }
s32 Init() { numBuffers = Config_DSoundOut.NumBuffers; // // Initialize DSound // GUID cGuid; try { if( Config_DSoundOut.Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", Config_DSoundOut.Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = BufferSizeBytes * numBuffers; desc.lpwfxFormat = &wfx; desc.dwFlags |= DSBCAPS_LOCSOFTWARE; desc.dwFlags |= DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc,&buffer_,0) ) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(u32 i=0;i<numBuffers;i++) { // [Air] note: wfx.nBlockAlign modifier was *10 -- seems excessive to me but maybe // it was needed for some quirky driver? Theoretically we want the notification as soon // as possible after the buffer has finished playing. buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(numBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
s32 Init() { CoInitializeEx( NULL, COINIT_MULTITHREADED ); // // Initialize DSound // GUID cGuid; try { if( m_Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", m_Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY; desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers; desc.lpwfxFormat = &wfx; // Try a hardware buffer first, and then fall back on a software buffer if // that one fails. desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) { if( m_UseHardware ) { desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) || buffer == NULL ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(uint i=0;i<m_NumBuffers;i++) { buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(m_NumBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
// This routine is called during IOCTL_POWER_CAPABILITIES processing. It // returns TRUE if successful and FALSE if not. The caller is expected to // destroy the CDiskPower object if this routine fails. BOOL CDiskPower::Init(CDisk *pDiskParent) { DWORD dwStatus; GUID gPMClass; int nPriority = 250; // THREAD_PRIORITY_ABOVE_NORMAL HANDLE hActive = NULL; BOOL fOk = TRUE; PREFAST_DEBUGCHK(pDiskParent != NULL); DEBUGMSG(ZONE_INIT, (_T("+CDiskPower::Init(): parent is 0x%08x\r\n"), pDiskParent)); // record the parent device m_pDisk = pDiskParent; // get a pointer to the PM APIs we need if(fOk) { HMODULE hmCoreDll = LoadLibrary(L"coredll.dll"); if(hmCoreDll == NULL) { DEBUGMSG(ZONE_INIT || ZONE_ERROR, (_T("CDevicePower::Init: LoadLibrary('coredll.dll') failed %d\r\n"), GetLastError())); fOk = FALSE; } else { m_pfnDevicePowerNotify = (DWORD ((*)(PVOID, CEDEVICE_POWER_STATE, DWORD))) GetProcAddress(hmCoreDll, L"DevicePowerNotify"); if(m_pfnDevicePowerNotify == NULL) { DEBUGMSG(ZONE_INIT || ZONE_ERROR, (_T("CDevicePower::Init: GetProcAddress('DevicePowerNotify') failed %d\r\n"), GetLastError())); fOk = FALSE; } // we're explicitly linked with coredll so we don't need the handle FreeLibrary(hmCoreDll); } } // read registry configuration if(fOk) { HKEY hk; BOOL fGotClass = FALSE; WCHAR szClass[64] = {0}; // big enough for a GUID // determine the power class we are advertising dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_pDisk->m_szDeviceKey, 0, 0, &hk); if(dwStatus == ERROR_SUCCESS) { // read the PM class DWORD dwSize = sizeof(szClass); dwStatus = RegQueryValueEx(hk, L"PowerClass", NULL, NULL, (LPBYTE) szClass, &dwSize); if(dwStatus == ERROR_SUCCESS) { fGotClass = TRUE; } // get the inactivity timeout DWORD dwValue; dwSize = sizeof(dwValue); dwStatus = RegQueryValueEx(hk, L"InactivityTimeout", NULL, NULL, (LPBYTE) &dwValue, &dwSize); if(dwStatus == ERROR_SUCCESS) { m_dwPowerTimeout = dwValue; } DEBUGMSG(ZONE_INIT, (_T("CDiskPower::Init: inactivity timeout is %u ms\r\n"), m_dwPowerTimeout)); // get the inactivity timeout dwSize = sizeof(dwValue); dwStatus = RegQueryValueEx(hk, L"TimeoutDx", NULL, NULL, (LPBYTE) &dwValue, &dwSize); if(dwStatus == ERROR_SUCCESS) { if(VALID_DX((CEDEVICE_POWER_STATE)dwValue) && dwValue != D3) { m_timeoutDx = (CEDEVICE_POWER_STATE) dwValue; } else { DEBUGMSG(ZONE_WARNING, (_T("CDiskPower::Init: invalid or unsupported timeout device power state %d (0x%x)\r\n"), dwValue, dwValue)); } } DEBUGMSG(ZONE_INIT, (_T("CDiskPower::Init: timeout state is D%d\r\n"), m_timeoutDx)); // get the inactivity timeout dwSize = sizeof(dwValue); dwStatus = RegQueryValueEx(hk, L"InactivityPriority256", NULL, NULL, (LPBYTE) &dwValue, &dwSize); if(dwStatus == ERROR_SUCCESS) { nPriority = (int) dwValue; } DEBUGMSG(ZONE_INIT, (_T("CDiskPower::Init: inactivity timeout thread priority is %d\r\n"), nPriority)); RegCloseKey(hk); } // did we get a class string? if(!fGotClass) { // no, use the default disk class wcsncpy(szClass, PMCLASS_BLOCK_DEVICE, dim(szClass)); szClass[dim(szClass) - 1] = 0; } // convert to a GUID fOk = GUIDFromString(szClass, &gPMClass); if(!fOk) { DEBUGMSG(ZONE_WARNING || ZONE_INIT, (_T("CDiskPower::Init: invalid power management class '%s'\r\n"), szClass)); } } // get our active key from the registry if(fOk) { HKEY hk; dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_pDisk->m_szActiveKey, 0, 0, &hk); if(dwStatus == ERROR_SUCCESS) { DWORD dwValue; DWORD dwSize = sizeof(dwValue); dwStatus = RegQueryValueEx(hk, DEVLOAD_HANDLE_VALNAME, NULL, NULL, (LPBYTE) &dwValue, &dwSize); if(dwStatus != ERROR_SUCCESS) { DEBUGMSG(ZONE_WARNING || ZONE_INIT, (_T("CDiskPower::Init: can't read '%s' from '%s'\r\n"), DEVLOAD_HANDLE_VALNAME, m_pDisk->m_szActiveKey)); fOk = FALSE; } else { DEBUGCHK(dwValue != 0); hActive = (HANDLE) dwValue; } } } // figure out the name we are using if(fOk) { WCHAR szName[MAX_PATH]; DWORD dwIndex = 0; do { DWORD dwSize = sizeof(szName); GUID gClass; fOk = EnumDeviceInterfaces(hActive, dwIndex, &gClass, szName, &dwSize); if(fOk && gPMClass == gClass) { // we found the interface break; } dwIndex++; } while(fOk); DEBUGMSG(!fOk && (ZONE_WARNING || ZONE_INIT), (_T("CDiskPower::Init: can't find PM interface\r\n"))); // did we find the name? if(fOk) { // yes, allocate a name buffer to use to talk to the power manager DWORD dwChars = wcslen(PMCLASS_BLOCK_DEVICE) + wcslen(szName) + 2; // class + separator + name + null LPWSTR pszPMName = (LPWSTR) LocalAlloc(LPTR, dwChars * sizeof(WCHAR)); fOk = FALSE; // assume failure if(pszPMName) { HRESULT hr = StringCchPrintfW(pszPMName, dwChars, L"{%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x}\\%s", gPMClass.Data1, gPMClass.Data2, gPMClass.Data3, (gPMClass.Data4[0] << 8) + gPMClass.Data4[1], gPMClass.Data4[2], gPMClass.Data4[3], gPMClass.Data4[4], gPMClass.Data4[5], gPMClass.Data4[6], gPMClass.Data4[7], szName); if(SUCCEEDED(hr)) { m_pszPMName = (LPCWSTR) pszPMName; fOk = TRUE; } } DEBUGMSG(!fOk && (ZONE_WARNING || ZONE_INIT), (_T("CDiskPower::Init: can't find PM interface\r\n"))); } } // create an event to tell the timeout thread about activity if(fOk) { m_hevPowerSignal = CreateEvent(NULL, FALSE, FALSE, NULL); m_hevDummy = CreateEvent(NULL, FALSE, FALSE, NULL); if(!m_hevPowerSignal || !m_hevDummy) { DEBUGMSG(ZONE_WARNING || ZONE_INIT, (_T("CDiskPower::Init: couldn't create status events\r\n"))); fOk = FALSE; } } // create the timeout thread if(fOk) { m_htPower = CreateThread(NULL, 0, DiskPowerThreadStub, this, 0, NULL); if(!m_htPower) { DEBUGMSG(ZONE_WARNING || ZONE_INIT, (_T("CDiskPower::Init: CreateThread() failed %d\r\n"), GetLastError())); fOk = FALSE; } else { BOOL fSuccess = CeSetThreadPriority(m_htPower, nPriority); DEBUGMSG(!fSuccess && (ZONE_WARNING || ZONE_INIT), (_T("CDiskPower::Init: CeSetThreadPriority(%d) failed %d\r\n"), nPriority, GetLastError())); } } // disable the standby timer, since the PM is going to be controlling // the disk power state if(fOk) { if(!m_pDisk->SendDiskPowerCommand(ATA_NEW_CMD_IDLE, 0)) { DEBUGMSG(ZONE_WARNING || ZONE_INIT, (_T("CDiskPower::Init: disable standby timer failed\r\n"))); } } // on error, cleanup will happen in the destructor DEBUGMSG(ZONE_INIT, (_T("-CDiskPower::Init(): returning %d\r\n"), fOk)); return fOk; }
bool _ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { int wmId,wmEvent; int tSel = 0; switch(uMsg) { case WM_INITDIALOG: { wchar_t temp[128]; haveGuid = !FAILED(GUIDFromString(m_Device, &DevGuid)); SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0); ndevs=0; DirectSoundEnumerate( DSEnumCallback, NULL ); tSel=-1; for(int i=0;i<ndevs;i++) { SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_ADDSTRING,0,(LPARAM)m_devices[i].name.wc_str()); if(haveGuid && IsEqualGUID(m_devices[i].guid,DevGuid) || tSel < 0 && !m_devices[i].hasGuid) tSel = i; } if(tSel>=0) SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_SETCURSEL,tSel,0); INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 ); SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,m_NumBuffers); swprintf_s(temp, L"%d (%d ms latency)",m_NumBuffers, 1000 / (96000 / (m_NumBuffers * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp); SET_CHECK( IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus ); SET_CHECK( IDC_USE_HARDWARE, m_UseHardware ); } break; case WM_COMMAND: { wchar_t temp[128]; wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDOK: { int i = (int)SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_GETCURSEL,0,0); if(!m_devices[i].hasGuid) { m_Device[0] = 0; // clear device name to "" } else { swprintf_s(temp, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", m_devices[i].guid.Data1, m_devices[i].guid.Data2, m_devices[i].guid.Data3, m_devices[i].guid.Data4[0], m_devices[i].guid.Data4[1], m_devices[i].guid.Data4[2], m_devices[i].guid.Data4[3], m_devices[i].guid.Data4[4], m_devices[i].guid.Data4[5], m_devices[i].guid.Data4[6], m_devices[i].guid.Data4[7] ); m_Device = temp; } m_NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 ); if( m_NumBuffers < 2 ) m_NumBuffers = 2; if( m_NumBuffers > MAX_BUFFER_COUNT ) m_NumBuffers = MAX_BUFFER_COUNT; EndDialog(hWnd,0); } break; case IDCANCEL: EndDialog(hWnd,0); break; HANDLE_CHECK( IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus ); HANDLE_CHECK( IDC_USE_HARDWARE, m_UseHardware ); default: return FALSE; } } break; case WM_HSCROLL: { wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch(wmId) { //case TB_ENDTRACK: //case TB_THUMBPOSITION: case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: wmEvent = (int)SendMessage((HWND)lParam,TBM_GETPOS,0,0); case TB_THUMBTRACK: { wchar_t temp[128]; if( wmEvent < 2 ) wmEvent = 2; if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT; SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent); swprintf_s(temp,L"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize))); SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp); break; } default: return FALSE; } } break; default: return FALSE; } return TRUE; }