void InputHandler_Win32_Pump::InputThreadMain() { if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ) LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set Pump thread priority") ); /* Enable priority boosting. */ SetThreadPriorityBoost( GetCurrentThread(), FALSE ); vector<WindowsFileIO *> apSources; for( int i = 0; i < NUM_PUMPS; ++i ) { if( m_pDevice[i].io.IsOpen() ) apSources.push_back( &m_pDevice[i].io ); } while( !m_bShutdown ) { CHECKPOINT; int iActual = 0, iVal = 0; int iRet = WindowsFileIO::read_several( apSources, &iVal, iActual, 0.100f ); CHECKPOINT; if( iRet <= 0 ) continue; /* no event */ HandleInput( iActual, iVal ); InputHandler::UpdateTimer(); } CHECKPOINT; }
MessageWindow::MessageWindow( const RString &sClassName ) { AppInstance inst; WNDCLASS WindowClass = { CS_OWNDC | CS_BYTEALIGNCLIENT, WndProc, 0, /* cbClsExtra */ 0, /* cbWndExtra */ inst, /* hInstance */ NULL, /* set icon later */ LoadCursor( NULL, IDC_ARROW ), /* default cursor */ NULL, /* hbrBackground */ NULL, /* lpszMenuName */ sClassName /* lpszClassName */ }; if( !RegisterClassA(&WindowClass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS ) RageException::Throw( "%s", werr_ssprintf( GetLastError(), "RegisterClass" ).c_str() ); // XXX: on 2k/XP, use HWND_MESSAGE as parent m_hWnd = CreateWindow( sClassName, sClassName, WS_DISABLED, 0, 0, 0, 0, NULL, NULL, inst, NULL ); ASSERT( m_hWnd != NULL ); SetProp( m_hWnd, "MessageWindow", this ); }
void RageSound_DSound_Software::MixerThread() { if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) ) if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) ) LOG->Warn(werr_ssprintf(GetLastError(), "Failed to set sound thread priority")); while( !shutdown_mixer_thread ) { char *locked_buf; unsigned len; const int64_t play_pos = pcm->GetOutputPosition(); /* must be called before get_output_buf */ if( !pcm->get_output_buf(&locked_buf, &len, chunksize()) ) { Sleep( chunksize()*1000 / samplerate ); continue; } this->Mix( (int16_t *) locked_buf, len/bytes_per_frame, play_pos, pcm->GetPosition() ); pcm->release_output_buf(locked_buf, len); } /* I'm not sure why, but if we don't stop the stream now, then the thread will take * 90ms (our buffer size) longer to close. */ pcm->Stop(); }
static void AdjustVideoModeParams( VideoModeParams &p ) { DEVMODE dm; ZERO( dm ); dm.dmSize = sizeof(dm); if( !EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) ) { p.rate = 60; LOG->Warn( "%s", werr_ssprintf(GetLastError(), "EnumDisplaySettings failed").c_str() ); return; } /* On a nForce 2 IGP on Windows 98, dm.dmDisplayFrequency sometimes * (but not always) is 0. * * MSDN: When you call the EnumDisplaySettings function, the * dmDisplayFrequency member may return with the value 0 or 1. * These values represent the display hardware's default refresh rate. * This default rate is typically set by switches on a display card or * computer motherboard, or by a configuration program that does not * use Win32 display functions such as ChangeDisplaySettings. */ if( !(dm.dmFields & DM_DISPLAYFREQUENCY) || dm.dmDisplayFrequency == 0 || dm.dmDisplayFrequency == 1 ) { p.rate = 60; LOG->Warn( "EnumDisplaySettings doesn't know what the refresh rate is. %d %d %d", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel ); } else { p.rate = dm.dmDisplayFrequency; } }
void ArchHooks_Win32::BoostPriority() { /* We just want a slight boost, so we don't skip needlessly if something happens * in the background. We don't really want to be high-priority--above normal should * be enough. However, ABOVE_NORMAL_PRIORITY_CLASS is only supported in Win2000 * and later. */ OSVERSIONINFO version; version.dwOSVersionInfoSize=sizeof(version); if( !GetVersionEx(&version) ) { LOG->Warn( werr_ssprintf(GetLastError(), "GetVersionEx failed") ); return; } #ifndef ABOVE_NORMAL_PRIORITY_CLASS #define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000 #endif DWORD pri = HIGH_PRIORITY_CLASS; if( version.dwMajorVersion >= 5 ) pri = ABOVE_NORMAL_PRIORITY_CLASS; /* Be sure to boost the app, not the thread, to make sure the * sound thread stays higher priority than the main thread. */ SetPriorityClass( GetCurrentProcess(), pri ); }
void MovieTexture_FFMpeg::DecoderThread() { #if defined(_WINDOWS) /* Windows likes to boost priority when processes come out of a wait state. We don't * want that, since it'll result in us having a small priority boost after each movie * frame, resulting in skips in the gameplay thread. */ if( !SetThreadPriorityBoost(GetCurrentThread(), TRUE) && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED ) LOG->Warn( werr_ssprintf(GetLastError(), "SetThreadPriorityBoost failed") ); #endif CHECKPOINT; while( m_State != DECODER_QUIT ) { if( m_ImageWaiting == FRAME_NONE ) DecodeFrame(); /* If we still have no frame, we're at EOF and we didn't loop. */ if( m_ImageWaiting != FRAME_DECODED ) { usleep( 10000 ); continue; } const float fTime = CheckFrameTime(); if( fTime == -1 ) // skip frame { DiscardFrame(); } else if( fTime > 0 ) // not time to decode a new frame yet { /* This needs to be relatively short so that we wake up quickly * from being paused or for changes in m_Rate. */ usleep( 10000 ); } else // fTime == 0 { { /* The only reason m_BufferFinished might be non-zero right now (before * ConvertFrame()) is if we're quitting. */ int n = m_BufferFinished.GetValue(); ASSERT_M( n == 0 || m_State == DECODER_QUIT, ssprintf("%i, %i", n, m_State) ); } ConvertFrame(); /* We just went into FRAME_WAITING. Don't actually check; the main thread * will change us back to FRAME_NONE without locking, and poke m_BufferFinished. * Don't time out on this; if a new screen has started loading, this might not * return for a while. */ m_BufferFinished.Wait( false ); /* If the frame wasn't used, then we must be shutting down. */ ASSERT_M( m_ImageWaiting == FRAME_NONE || m_State == DECODER_QUIT, ssprintf("%i, %i", m_ImageWaiting, m_State) ); } } CHECKPOINT; }
RString ArchHooks_Win32::GetClipboard() { HGLOBAL hgl; LPTSTR lpstr; RString ret; // First make sure that the clipboard actually contains a string // (or something stringifiable) if(unlikely( !IsClipboardFormatAvailable( CF_TEXT ) )) return ""; // Yes. All this mess just to gain access to the string stored by the clipboard. // I'm having flashbacks to Berkeley sockets. if(unlikely( !OpenClipboard( NULL ) )) { LOG->Warn(werr_ssprintf( GetLastError(), "InputHandler_DirectInput: OpenClipboard() failed" )); return ""; } hgl = GetClipboardData( CF_TEXT ); if(unlikely( hgl == NULL )) { LOG->Warn(werr_ssprintf( GetLastError(), "InputHandler_DirectInput: GetClipboardData() failed" )); CloseClipboard(); return ""; } lpstr = (LPTSTR) GlobalLock( hgl ); if(unlikely( lpstr == NULL )) { LOG->Warn(werr_ssprintf( GetLastError(), "InputHandler_DirectInput: GlobalLock() failed" )); CloseClipboard(); return ""; } // And finally, we have a char (or wchar_t) array of the clipboard contents, // pointed to by sToPaste. // (Hopefully.) #ifdef UNICODE ret = WStringToRString( wstring()+*lpstr ); #else ret = RString( lpstr ); #endif // And now we clean up. GlobalUnlock( hgl ); CloseClipboard(); return ret; }
void RageSoundDriver_WaveOut::MixerThread() { if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) ) LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set sound thread priority") ); while( !m_bShutdown ) { while( GetData() ) ; WaitForSingleObject( m_hSoundEvent, 10 ); } waveOutReset( m_hWaveOut ); }
wstring ConvertCodepageToWString( RString s, int iCodePage ) { if( s.empty() ) return wstring(); int iBytes = MultiByteToWideChar( iCodePage, 0, s.data(), s.size(), NULL, 0 ); ASSERT_M( iBytes > 0, werr_ssprintf( GetLastError(), "MultiByteToWideChar" ).c_str() ); wchar_t *pTemp = new wchar_t[iBytes]; MultiByteToWideChar( iCodePage, 0, s.data(), s.size(), pTemp, iBytes ); wstring sRet( pTemp, iBytes ); delete [] pTemp; return sRet; }
void GraphicsWindow::Initialize( bool bD3D ) { // A few things need to be handled differently for D3D. g_bD3D = bD3D; AppInstance inst; do { const wstring wsClassName = RStringToWstring( g_sClassName ); WNDCLASSW WindowClassW = { CS_OWNDC | CS_BYTEALIGNCLIENT, GraphicsWindow_WndProc, 0, /* cbClsExtra */ 0, /* cbWndExtra */ inst, /* hInstance */ NULL, /* set icon later */ LoadCursor( NULL, IDC_ARROW ), /* default cursor */ NULL, /* hbrBackground */ NULL, /* lpszMenuName */ wsClassName.c_str() /* lpszClassName */ }; m_bWideWindowClass = true; if( RegisterClassW( &WindowClassW ) ) break; WNDCLASS WindowClassA = { CS_OWNDC | CS_BYTEALIGNCLIENT, GraphicsWindow_WndProc, 0, /* cbClsExtra */ 0, /* cbWndExtra */ inst, /* hInstance */ NULL, /* set icon later */ LoadCursor( NULL, IDC_ARROW ), /* default cursor */ NULL, /* hbrBackground */ NULL, /* lpszMenuName */ g_sClassName /* lpszClassName */ }; m_bWideWindowClass = false; if( !RegisterClassA( &WindowClassA ) ) RageException::Throw( "%s", werr_ssprintf( GetLastError(), "RegisterClass" ).c_str() ); } while(0); g_iQueryCancelAutoPlayMessage = RegisterWindowMessage( "QueryCancelAutoPlay" ); }
RString ConvertWstringToCodepage( wstring s, int iCodePage ) { if( s.empty() ) return RString(); int iBytes = WideCharToMultiByte( iCodePage, 0, s.data(), s.size(), NULL, 0, NULL, FALSE ); ASSERT_M( iBytes > 0, werr_ssprintf( GetLastError(), "WideCharToMultiByte" ).c_str() ); char * buf = new char[iBytes]; WideCharToMultiByte( CP_ACP, 0, s.data(), s.size(), buf, iBytes, NULL, FALSE ); RString ret( buf ); delete[] buf; return ret; }
CString ConvertWstringToACP( wstring s ) { if( s.empty() ) return ""; int iBytes = WideCharToMultiByte( CP_ACP, 0, s.data(), s.size(), NULL, 0, NULL, FALSE ); ASSERT_M( iBytes > 0, werr_ssprintf( GetLastError(), "WideCharToMultiByte" ).c_str() ); CString ret; WideCharToMultiByte( CP_ACP, 0, s.data(), s.size(), ret.GetBuf( iBytes ), iBytes, NULL, FALSE ); ret.RelBuf( iBytes ); return ret; }
static HKEY OpenRegKey( const RString &sKey, RegKeyMode mode, bool bWarnOnError = true ) { RString sSubkey; HKEY hType; if( !GetRegKeyType(sKey, sSubkey, hType) ) return NULL; HKEY hRetKey; LONG retval = RegOpenKeyEx( hType, sSubkey, 0, (mode==READ) ? KEY_READ:KEY_WRITE, &hRetKey ); if ( retval != ERROR_SUCCESS ) { if( bWarnOnError ) LOG->Warn( werr_ssprintf(retval, "RegOpenKeyEx(%x,%s) error", hType, sSubkey.c_str()) ); return NULL; } return hRetKey; }
bool VDDebugInfoInitFromFile( Context *pctx ) { if( pctx->Loaded() ) return true; pctx->sRawBlock = RString(); pctx->pRVAHeap = NULL; GetVDIPath( pctx->sFilename, ARRAYLEN(pctx->sFilename) ); pctx->sError = RString(); HANDLE h = CreateFile( pctx->sFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( h == INVALID_HANDLE_VALUE ) { pctx->sError = werr_ssprintf( GetLastError(), "CreateFile failed" ); return false; } do { DWORD dwFileSize = GetFileSize( h, NULL ); if( dwFileSize == INVALID_FILE_SIZE ) break; char *pBuf = pctx->sRawBlock.GetBuffer( dwFileSize ); if( pBuf == NULL ) break; DWORD dwActual; int iRet = ReadFile(h, pBuf, dwFileSize, &dwActual, NULL); CloseHandle(h); pctx->sRawBlock.ReleaseBuffer( dwActual ); if( !iRet || dwActual != dwFileSize ) break; if( VDDebugInfoInitFromMemory(pctx) ) return true; } while(0); VDDebugInfoDeinit(pctx); return false; }
/* Convert from the given codepage to UTF-8. Return true if successful. */ static bool CodePageConvert(CString &txt, int cp) { if( txt.size() == 0 ) return true; int size = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, txt.data(), txt.size(), NULL, 0); if( size == 0 ) { LOG->Trace("%s\n", werr_ssprintf(GetLastError(), "err: ").c_str()); return false; /* error */ } wstring out; out.append(size, ' '); /* Nonportable: */ size = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, txt.data(), txt.size(), (wchar_t *) out.data(), size); ASSERT( size != 0 ); txt = WStringToCString(out); return true; }
bool VDDebugInfoInitFromMemory( Context *pctx ) { if( pctx->sRawBlock[0] == '\x1f' && pctx->sRawBlock[1] == '\x8b' ) { RString sBufOut; RString sError; if( !GunzipString(pctx->sRawBlock, sBufOut, sError) ) { pctx->sError = werr_ssprintf( GetLastError(), "VDI error: %s", sError.c_str() ); return false; } pctx->sRawBlock = sBufOut; } const unsigned char *src = (const unsigned char *) pctx->sRawBlock.data(); pctx->pRVAHeap = NULL; static const char *header = "symbolic debug information"; if( memcmp(src, header, strlen(header)) ) { pctx->sError = "header doesn't match"; return false; } // Extract fields src += 64; pctx->nBuildNumber = *(int *)src; pctx->pRVAHeap = (const unsigned char *)(src + 20); pctx->nFirstRVA = *(const long *)(src + 16); pctx->pFuncNameHeap = (const char *)pctx->pRVAHeap - 4 + *(const long *)(src + 4); pctx->pSegments = (unsigned long (*)[2])(pctx->pFuncNameHeap + *(const long *)(src + 8)); pctx->nSegments = *(const long *)(src + 12); return true; }
bool RegistryAccess::GetRegSubKeys( const RString &sKey, vector<RString> &lst, const RString ®ex, bool bReturnPathToo ) { HKEY hKey = OpenRegKey( sKey, READ ); if( hKey == NULL ) return false; Regex re(regex); bool bError = false; for( int index = 0; ; ++index ) { FILETIME ft; char szBuffer[MAX_PATH]; DWORD iSize = sizeof(szBuffer); LONG iRet = RegEnumKeyEx( hKey, index, szBuffer, &iSize, NULL, NULL, NULL, &ft); if( iRet == ERROR_NO_MORE_ITEMS ) break; if( iRet != ERROR_SUCCESS ) { LOG->Warn( werr_ssprintf(iRet, "GetRegSubKeys(%p,%i) error", hKey, index) ); bError = true; break; } RString sStr( szBuffer, iSize ); if( re.Compare(sStr) ) { if( bReturnPathToo ) sStr = sKey + "\\" + sStr; lst.push_back( sStr ); } } RegCloseKey( hKey ); return !bError; }
int WindowsFileIO::finish_read(void *p) { LOG->Trace("this %p, %p", this, p); /* We do; get the result. It'll go into the original buf * we supplied on the original call; that's why buf is a * member instead of a local. */ unsigned long cnt; int ret = GetOverlappedResult(h, &ov, &cnt, FALSE); if(ret == 0 && (GetLastError() == ERROR_IO_PENDING || GetLastError() == ERROR_IO_INCOMPLETE)) return -1; queue_read(); if(ret == 0) { LOG->Warn(werr_ssprintf(GetLastError(), "Error reading Pump pad")); return -1; } memcpy( p, buf, cnt ); return cnt; }
int WindowsFileIO::read_several(const vector<WindowsFileIO *> &sources, void *p, int &actual, float timeout) { HANDLE *Handles = new HANDLE[sources.size()]; for( unsigned i = 0; i < sources.size(); ++i ) Handles[i] = sources[i]->h; int ret = WaitForMultipleObjectsEx( sources.size(), Handles, false, int(timeout * 1000), true); delete[] Handles; if( ret == -1 ) { LOG->Trace( werr_ssprintf(GetLastError(), "WaitForMultipleObjectsEx failed") ); return -1; } if( ret >= int(WAIT_OBJECT_0) && ret < int(WAIT_OBJECT_0+sources.size()) ) { actual = ret - WAIT_OBJECT_0; return sources[actual]->finish_read(p); } return 0; }
void InputHandler_Win32_Para::InputThreadMain() { if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) LOG->Warn(werr_ssprintf(GetLastError(), "Failed to set Para thread priority")); vector<WindowsFileIO *> sources; if( dev->io.IsOpen() ) sources.push_back( &dev->io ); while(!shutdown) { CHECKPOINT; int actual = 0, val = 0; int ret = WindowsFileIO::read_several(sources, &val, actual, 0.100f); CHECKPOINT; if(ret <= 0) continue; /* no event */ HandleInput( actual, val ); InputHandler::UpdateTimer(); } CHECKPOINT; }
RageFileObjDirect::~RageFileObjDirect() { bool bFailed = !FinalFlush(); if( m_iFD != -1 ) { if( close( m_iFD ) == -1 ) { WARN( ssprintf("Error closing %s: %s", this->m_sPath.c_str(), strerror(errno)) ); SetError( strerror(errno) ); bFailed = true; } } if( !(m_iMode & RageFile::WRITE) || (m_iMode & RageFile::STREAMED) ) return; /* We now have path written to MakeTempFilename(m_sPath). * Rename the temporary file over the real path. */ do { if( bFailed || WriteFailed() ) break; /* We now have path written to MakeTempFilename(m_sPath). Rename the * temporary file over the real path. This should be an atomic operation * with a journalling filesystem. That is, there should be no * intermediate state a JFS might restore the file we're writing (in the * case of a crash/powerdown) to an empty or partial file. */ RString sOldPath = MakeTempFilename(m_sPath); RString sNewPath = m_sPath; #if defined(WIN32) if( WinMoveFile(DoPathReplace(sOldPath), DoPathReplace(sNewPath)) ) return; /* We failed. */ int err = GetLastError(); const RString error = werr_ssprintf( err, "Error renaming \"%s\" to \"%s\"", sOldPath.c_str(), sNewPath.c_str() ); WARN( ssprintf("%s", error.c_str()) ); SetError( error ); break; #else if( rename( sOldPath, sNewPath ) == -1 ) { WARN( ssprintf("Error renaming \"%s\" to \"%s\": %s", sOldPath.c_str(), sNewPath.c_str(), strerror(errno)) ); SetError( strerror(errno) ); break; } if( m_iMode & RageFile::SLOW_FLUSH ) { RString sError; if( !FlushDir(Dirname(m_sPath), sError) ) { WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) ); SetError( sError ); } } // Success. return; #endif } while(0); // The write or the rename failed. Delete the incomplete temporary file. DoRemove( MakeTempFilename(m_sPath) ); }
/* Set the final window size, set the window text and icon, and then unhide the * window. */ void GraphicsWindow::CreateGraphicsWindow( const VideoModeParams &p, bool bForceRecreateWindow ) { g_CurrentParams = p; // Adjust g_CurrentParams to reflect the actual display settings. AdjustVideoModeParams( g_CurrentParams ); if( g_hWndMain == NULL || bForceRecreateWindow ) { int iWindowStyle = GetWindowStyle( p.windowed ); AppInstance inst; HWND hWnd = CreateWindow( g_sClassName, "app", iWindowStyle, 0, 0, 0, 0, NULL, NULL, inst, NULL ); if( hWnd == NULL ) RageException::Throw( "%s", werr_ssprintf( GetLastError(), "CreateWindow" ).c_str() ); /* If an old window exists, transfer focus to the new window before * deleting it, or some other window may temporarily get focus, which * can cause it to be resized. */ if( g_hWndMain != NULL ) { // While we change to the new window, don't do ChangeDisplaySettings in WM_ACTIVATE. g_bRecreatingVideoMode = true; SetForegroundWindow( hWnd ); g_bRecreatingVideoMode = false; GraphicsWindow::DestroyGraphicsWindow(); } g_hWndMain = hWnd; CrashHandler::SetForegroundWindow( g_hWndMain ); g_HDC = GetDC( g_hWndMain ); } // Update the window title. do { if( m_bWideWindowClass ) { if( SetWindowText( g_hWndMain, ConvertUTF8ToACP(p.sWindowTitle).c_str() ) ) break; } SetWindowTextA( g_hWndMain, ConvertUTF8ToACP(p.sWindowTitle) ); } while(0); // Update the window icon. if( g_hIcon != NULL ) { SetClassLong( g_hWndMain, GCL_HICON, (LONG) LoadIcon(NULL,IDI_APPLICATION) ); DestroyIcon( g_hIcon ); g_hIcon = NULL; } g_hIcon = IconFromFile( p.sIconFile ); if( g_hIcon != NULL ) SetClassLong( g_hWndMain, GCL_HICON, (LONG) g_hIcon ); /* The window style may change as a result of switching to or from fullscreen; * apply it. Don't change the WS_VISIBLE bit. */ int iWindowStyle = GetWindowStyle( p.windowed ); if( GetWindowLong( g_hWndMain, GWL_STYLE ) & WS_VISIBLE ) iWindowStyle |= WS_VISIBLE; SetWindowLong( g_hWndMain, GWL_STYLE, iWindowStyle ); RECT WindowRect; SetRect( &WindowRect, 0, 0, p.width, p.height ); AdjustWindowRect( &WindowRect, iWindowStyle, FALSE ); //LOG->Warn( "w = %d, h = %d", p.width, p.height ); const int iWidth = WindowRect.right - WindowRect.left; const int iHeight = WindowRect.bottom - WindowRect.top; // If windowed, center the window. int x = 0, y = 0; if( p.windowed ) { x = GetSystemMetrics(SM_CXSCREEN)/2-iWidth/2; y = GetSystemMetrics(SM_CYSCREEN)/2-iHeight/2; } /* Move and resize the window. SWP_FRAMECHANGED causes the above * SetWindowLong to take effect. */ if( !SetWindowPos( g_hWndMain, HWND_NOTOPMOST, x, y, iWidth, iHeight, SWP_FRAMECHANGED|SWP_SHOWWINDOW ) ) LOG->Warn( "%s", werr_ssprintf( GetLastError(), "SetWindowPos" ).c_str() ); SetForegroundWindow( g_hWndMain ); /* Pump messages quickly, to make sure the window is completely set up. * If we don't do this, then starting up in a D3D fullscreen window may * cause all other windows on the system to be resized. */ MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { GetMessage( &msg, NULL, 0, 0 ); DispatchMessage( &msg ); } }
void RageSoundDriver_WaveOut::SetupDecodingThread() { if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) ) LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set sound thread priority") ); }
/* Get the full path of the process running in iProcessID. On error, false is * returned and an error message is placed in sName. */ bool GetProcessFileName( uint32_t iProcessID, RString &sName ) { /* This method works in everything except for NT4, and only uses * kernel32.lib functions. */ do { HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, iProcessID ); if( hSnap == NULL ) { sName = werr_ssprintf( GetLastError(), "CreateToolhelp32Snapshot" ); break; } MODULEENTRY32 me; ZERO( me ); me.dwSize = sizeof(MODULEENTRY32); bool bRet = !!Module32First( hSnap, &me ); CloseHandle( hSnap ); if( bRet ) { sName = me.szExePath; return true; } sName = werr_ssprintf( GetLastError(), "Module32First" ); } while(0); // This method only works in NT/2K/XP. do { static HINSTANCE hPSApi = NULL; typedef DWORD (WINAPI* pfnGetProcessImageFileNameA)(HANDLE hProcess, LPSTR lpImageFileName, DWORD nSize); static pfnGetProcessImageFileNameA pGetProcessImageFileName = NULL; static bool bTried = false; if( !bTried ) { bTried = true; hPSApi = LoadLibrary("psapi.dll"); if( hPSApi == NULL ) { sName = werr_ssprintf( GetLastError(), "LoadLibrary" ); break; } else { pGetProcessImageFileName = (pfnGetProcessImageFileNameA) GetProcAddress( hPSApi, "GetProcessImageFileNameA" ); if( pGetProcessImageFileName == NULL ) { sName = werr_ssprintf( GetLastError(), "GetProcAddress" ); break; } } } if( pGetProcessImageFileName != NULL ) { HANDLE hProc = OpenProcess( PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, NULL, iProcessID ); if( hProc == NULL ) { sName = werr_ssprintf( GetLastError(), "OpenProcess" ); break; } char buf[1024]; int iRet = pGetProcessImageFileName( hProc, buf, sizeof(buf) ); CloseHandle( hProc ); if( iRet ) { if( iRet == sizeof(buf) ) buf[iRet-1] = 0; sName = buf; return true; } sName = werr_ssprintf( GetLastError(), "GetProcessImageFileName" ); } } while(0); return false; }
HICON IconFromSurface( const RageSurface *pSrcImg ) { RageSurface *pImg; { /* Round the width up to a multiple of 8, convert to 32-bit BGR, and reduce * to one-bit alpha. */ int iWidth = pSrcImg->w; iWidth = (iWidth+7) & ~7; pImg = CreateSurface( iWidth, pSrcImg->h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x80000000 ); RageSurfaceUtils::Blit( pSrcImg, pImg ); } RageSurfaceUtils::FlipVertically( pImg ); int iSize = sizeof(BITMAPINFOHEADER); int iSizeImage = 0; iSizeImage += pImg->h * pImg->pitch; /* image */ iSizeImage += (pImg->h * pImg->w) / 8; /* mask */ BITMAPINFOHEADER *pBitmap = (BITMAPINFOHEADER *) malloc( iSize + iSizeImage ); memset( pBitmap, 0, iSize + iSizeImage ); pBitmap->biSize = sizeof(BITMAPINFOHEADER); pBitmap->biWidth = pImg->w; pBitmap->biHeight = pImg->h * 2; pBitmap->biPlanes = 1; pBitmap->biBitCount = 32; pBitmap->biCompression = BI_RGB; pBitmap->biSizeImage = pImg->h * pImg->pitch; uint8_t *pImage = ((uint8_t *) pBitmap) + iSize; uint8_t *pMask = pImage + pImg->h * pImg->pitch; memcpy( pImage, pImg->pixels, pImg->h * pImg->pitch ); int iMaskPitch = pImg->w/8; for( int y = 0; y < pImg->h; ++y ) { int bit = 0x80; uint32_t *pRow = (uint32_t *) (pImage + y*pImg->pitch); uint8_t *pMaskRow = pMask + y*iMaskPitch; for( int x = 0; x < pImg->w; ++x ) { if( !(pRow[x] & pImg->fmt.Mask[3]) ) { /* Transparent; set this mask bit. */ *pMaskRow |= bit; pRow[x] = 0; } bit >>= 1; if( bit == 0 ) { bit = 0x80; ++pMaskRow; } } } HICON icon = CreateIconFromResourceEx( (BYTE *) pBitmap, iSize + iSizeImage, TRUE, 0x00030000, pImg->w, pImg->h, LR_DEFAULTCOLOR ); delete pImg; pImg = NULL; free( pBitmap ); if( icon == NULL ) { LOG->Trace( "%s", werr_ssprintf( GetLastError(), "CreateIconFromResourceEx" ).c_str() ); return NULL; } return icon; }
void RageSound_DSound_Software::SetupDecodingThread() { if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) ) LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set decoding thread priority") ); }
/* This function does not reset the video mode if it fails, because we might be trying * yet another video mode, so we'd just thrash the display. On fatal error, * LowLevelWindow_Win32::~LowLevelWindow_Win32 will call Shutdown(). */ CString LowLevelWindow_Win32::TryVideoMode( RageDisplay::VideoModeParams p, bool &bNewDeviceOut ) { ASSERT_M( p.bpp == 16 || p.bpp == 32, ssprintf("%i", p.bpp) ); bNewDeviceOut = false; /* We're only allowed to change the pixel format of a window exactly once. */ bool bCanSetPixelFormat = true; /* Do we have an old window? */ if( GraphicsWindow::GetHwnd() == NULL ) { /* No. Always create and show the window before changing the video mode. * Otherwise, some other window may have focus, and changing the video mode will * cause that window to be resized. */ GraphicsWindow::CreateGraphicsWindow( p ); GraphicsWindow::ConfigureGraphicsWindow( p ); } else { /* We already have a window. Assume that it's pixel format has already been * set. */ LOG->Trace("Setting new window, can't reuse old"); bCanSetPixelFormat = false; } ASSERT( GraphicsWindow::GetHwnd() ); /* Set the display mode: switch to a fullscreen mode or revert to windowed mode. */ LOG->Trace("SetScreenMode ..."); CString sErr = GraphicsWindow::SetScreenMode( p ); if( !sErr.empty() ) return sErr; PIXELFORMATDESCRIPTOR PixelFormat; int iPixelFormat = ChooseWindowPixelFormat( p, &PixelFormat ); if( iPixelFormat == 0 ) { /* Destroy the window. */ DestroyGraphicsWindowAndOpenGLContext(); return "Pixel format not found"; } bool bNeedToSetPixelFormat = false; { /* We'll need to recreate it if the pixel format is going to change. We * aren't allowed to change the pixel format twice. */ PIXELFORMATDESCRIPTOR DestPixelFormat; ZERO( DestPixelFormat ); DescribePixelFormat( GraphicsWindow::GetHDC(), iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &DestPixelFormat ); if( memcmp( &DestPixelFormat, &g_CurrentPixelFormat, sizeof(PIXELFORMATDESCRIPTOR) ) ) { LOG->Trace("Reset: pixel format changing" ); bNeedToSetPixelFormat = true; } } if( bNeedToSetPixelFormat && !bCanSetPixelFormat ) { /* * The screen mode has changed, so we need to set the pixel format. If we're * not allowed to do so, destroy the window and make a new one. * * For some reason, if we destroy the old window before creating the new one, * the "fullscreen apps go under the taskbar" glitch will happen when we quit. * We have to create the new window first. */ LOG->Trace( "Mode requires new pixel format, and we've already set one; resetting OpenGL context" ); if( g_HGLRC != NULL ) { wglMakeCurrent( NULL, NULL ); wglDeleteContext( g_HGLRC ); g_HGLRC = NULL; } GraphicsWindow::RecreateGraphicsWindow(p); // DestroyGraphicsWindowAndOpenGLContext(); // GraphicsWindow::CreateGraphicsWindow( p ); bNewDeviceOut = true; } GraphicsWindow::ConfigureGraphicsWindow( p ); GraphicsWindow::SetVideoModeParams( p ); if( bNeedToSetPixelFormat ) { /* Set the pixel format. */ if( !SetPixelFormat(GraphicsWindow::GetHDC(), iPixelFormat, &PixelFormat) ) { /* Destroy the window. */ DestroyGraphicsWindowAndOpenGLContext(); return werr_ssprintf( GetLastError(), "Pixel format failed" ); } DescribePixelFormat( GraphicsWindow::GetHDC(), iPixelFormat, sizeof(g_CurrentPixelFormat), &g_CurrentPixelFormat ); DumpPixelFormat( g_CurrentPixelFormat ); } if( g_HGLRC == NULL ) { g_HGLRC = wglCreateContext( GraphicsWindow::GetHDC() ); if ( g_HGLRC == NULL ) { DestroyGraphicsWindowAndOpenGLContext(); return hr_ssprintf( GetLastError(), "wglCreateContext" ); } if( !wglMakeCurrent( GraphicsWindow::GetHDC(), g_HGLRC ) ) { DestroyGraphicsWindowAndOpenGLContext(); return hr_ssprintf( GetLastError(), "wglCreateContext" ); } } return ""; // we set the video mode successfully }
void InputHandler_DInput::InputThreadMain() { if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) LOG->Warn(werr_ssprintf(GetLastError(), "Failed to set DirectInput thread priority")); /* Enable priority boosting. */ SetThreadPriorityBoost( GetCurrentThread(), FALSE ); vector<DIDevice*> BufferedDevices, UnbufferedDevices; HANDLE Handle = CreateEvent(NULL, FALSE, FALSE, NULL); for( unsigned i = 0; i < Devices.size(); ++i ) { if( !Devices[i].buffered ) { UnbufferedDevices.push_back( &Devices[i] ); continue; } BufferedDevices.push_back( &Devices[i] ); IDirectInputDevice2_Unacquire(Devices[i].Device); HRESULT hr = IDirectInputDevice2_SetEventNotification(Devices[i].Device, Handle); if( FAILED(hr) ) LOG->Warn("IDirectInputDevice2_SetEventNotification failed on %i", i); IDirectInputDevice2_Acquire(Devices[i].Device); } while(!shutdown) { m_DebugTimer.StartUpdate(); CHECKPOINT; if( BufferedDevices.size() ) { /* Update buffered devices. */ PollAndAcquireDevices(); int ret = WaitForSingleObjectEx( Handle, 50, true ); if( ret == -1 ) { LOG->Trace( werr_ssprintf(GetLastError(), "WaitForSingleObjectEx failed") ); continue; } if( ret == WAIT_OBJECT_0 ) { RageTimer now; for( unsigned i = 0; i < BufferedDevices.size(); ++i ) UpdateBuffered( *BufferedDevices[i], now ); } } CHECKPOINT; /* If we have no buffered devices, we didn't delay at WaitForMultipleObjectsEx. */ if( BufferedDevices.size() == 0 ) usleep( 50000 ); CHECKPOINT; m_DebugTimer.EndUpdate(); } CHECKPOINT; for( unsigned i = 0; i < Devices.size(); ++i ) { if( !Devices[i].buffered ) continue; IDirectInputDevice2_Unacquire(Devices[i].Device); IDirectInputDevice2_SetEventNotification( Devices[i].Device, NULL ); } CloseHandle(Handle); }