예제 #1
0
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;
}
예제 #2
0
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();
}
예제 #4
0
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;
	}
}
예제 #5
0
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 );
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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 );
}
예제 #9
0
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;
}
예제 #10
0
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" );
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
	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;
	}
예제 #15
0
/* 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;
}
예제 #16
0
	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;
	}
예제 #17
0
bool RegistryAccess::GetRegSubKeys( const RString &sKey, vector<RString> &lst, const RString &regex, 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;
}
예제 #18
0
파일: USB.cpp 프로젝트: BitMax/openitg
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;
}
예제 #19
0
파일: USB.cpp 프로젝트: BitMax/openitg
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) );
}
예제 #22
0
/* 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 );
	}
}
예제 #23
0
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;
}
예제 #25
0
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") );
}
예제 #27
0
/* 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
}
예제 #28
0
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);
}