123
This commit is contained in:
519
BinkSDK/examw32.c
Normal file
519
BinkSDK/examw32.c
Normal file
@@ -0,0 +1,519 @@
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## EXAMW32.C ##
|
||||
//## ##
|
||||
//## Example of using Bink with BinkBuffers on Win32 ##
|
||||
//## ##
|
||||
//## Author: Jeff Roberts ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## Copyright (C) RAD Game Tools, Inc. ##
|
||||
//## ##
|
||||
//## For technical support, contact RAD Game Tools at 425 - 893 - 4300. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
|
||||
#include "bink.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//
|
||||
// Example globals
|
||||
//
|
||||
|
||||
static HBINK Bink = 0;
|
||||
static HBINKBUFFER Bink_buffer = 0;
|
||||
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## Clear_to_black - just fills a window with black pixels. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
static void Clear_to_black( HWND window )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC dc;
|
||||
|
||||
//
|
||||
// Get the repaint DC and then fill the window with black.
|
||||
//
|
||||
|
||||
dc = BeginPaint( window, &ps );
|
||||
|
||||
PatBlt( dc, 0, 0, 4096, 4096, BLACKNESS );
|
||||
|
||||
EndPaint( window, &ps );
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## WindowProc - the main window message procedure. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
LONG FAR PASCAL WindowProc( HWND window,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam )
|
||||
{
|
||||
|
||||
switch( message )
|
||||
{
|
||||
//
|
||||
// Just close the window if the user hits a key.
|
||||
//
|
||||
|
||||
case WM_CHAR:
|
||||
DestroyWindow( window );
|
||||
break;
|
||||
|
||||
//
|
||||
// Pause/resume the video when the focus changes.
|
||||
//
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
BinkPause( Bink, 1 );
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
BinkPause( Bink, 0 );
|
||||
break;
|
||||
|
||||
//
|
||||
// Handle the window paint messages.
|
||||
//
|
||||
|
||||
case WM_PAINT:
|
||||
Clear_to_black( window );
|
||||
|
||||
//
|
||||
// Redraw the frame (or the color mask for overlays).
|
||||
//
|
||||
|
||||
if ( Bink_buffer )
|
||||
BinkBufferBlit( Bink_buffer, 0, 1 );
|
||||
|
||||
return( 0 );
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
return( 1 );
|
||||
|
||||
//
|
||||
// Handle the window being moved.
|
||||
//
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
//
|
||||
// Is the window even being moved?
|
||||
//
|
||||
|
||||
if ( ! ( ( ( WINDOWPOS* )lparam )->flags & SWP_NOMOVE ) )
|
||||
{
|
||||
|
||||
if ( Bink_buffer )
|
||||
{
|
||||
S32 x,y;
|
||||
|
||||
//
|
||||
// Yup, it's being moved - ask the BinkBuffer API to align the
|
||||
// coordinates to a fast boundary.
|
||||
//
|
||||
|
||||
x = ( ( WINDOWPOS* )lparam )->x;
|
||||
y = ( ( WINDOWPOS* )lparam )->y;
|
||||
BinkBufferCheckWinPos( Bink_buffer, &x, &y );
|
||||
( ( WINDOWPOS* )lparam )->x = x;
|
||||
( ( WINDOWPOS* )lparam )->y = y;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
//
|
||||
// Tell the BinkBuffer API when the window moves.
|
||||
//
|
||||
|
||||
if ( Bink_buffer )
|
||||
BinkBufferSetOffset( Bink_buffer, 0, 0 );
|
||||
break;
|
||||
|
||||
//
|
||||
// Post the quit message.
|
||||
//
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage( 0 );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
//
|
||||
// Call the OS default window procedure.
|
||||
//
|
||||
|
||||
return( DefWindowProc( window, message, wparam, lparam ) );
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## Build_window_handle - creates a window class and window handle. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
static HWND Build_window_handle( HINSTANCE instance,
|
||||
HINSTANCE previous_instance )
|
||||
{
|
||||
//
|
||||
// Create the window class if this is the first instance.
|
||||
//
|
||||
|
||||
if ( !previous_instance )
|
||||
{
|
||||
WNDCLASS wc;
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = WindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = instance;
|
||||
wc.hIcon = LoadIcon( instance, MAKEINTRESOURCE( 101 ) );
|
||||
wc.hCursor = LoadCursor( 0, IDC_ARROW );;
|
||||
wc.hbrBackground = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = "BinkExam";
|
||||
|
||||
//
|
||||
// Try to register the class.
|
||||
//
|
||||
|
||||
if ( !RegisterClass( &wc ) )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Return the new window with a tiny initial default size (it is resized
|
||||
// later on with the help of the BinkBuffer API).
|
||||
//
|
||||
|
||||
return( CreateWindow( "BinkExam",
|
||||
"Bink Example Player",
|
||||
WS_CAPTION|WS_POPUP|WS_CLIPCHILDREN|
|
||||
WS_SYSMENU|WS_MINIMIZEBOX,
|
||||
64, 64,
|
||||
64, 64,
|
||||
0, 0, instance,0 ) );
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## Show_next_frame - advances to the next Bink frame. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
static void Show_next_frame( HBINK bink,
|
||||
HBINKBUFFER bink_buffer,
|
||||
HWND window )
|
||||
{
|
||||
//
|
||||
// Decompress the Bink frame.
|
||||
//
|
||||
|
||||
BinkDoFrame( bink );
|
||||
|
||||
//
|
||||
// Lock the BinkBuffer so that we can copy the decompressed frame into it.
|
||||
//
|
||||
|
||||
if ( BinkBufferLock( bink_buffer ) )
|
||||
{
|
||||
//
|
||||
// Copy the decompressed frame into the BinkBuffer (this might be on-screen).
|
||||
//
|
||||
|
||||
BinkCopyToBuffer( bink,
|
||||
bink_buffer->Buffer,
|
||||
bink_buffer->BufferPitch,
|
||||
bink_buffer->Height,
|
||||
0,0,
|
||||
bink_buffer->SurfaceType);
|
||||
|
||||
//
|
||||
// Unlock the BinkBuffer.
|
||||
//
|
||||
|
||||
BinkBufferUnlock( bink_buffer );
|
||||
}
|
||||
|
||||
//
|
||||
// Tell the BinkBuffer to blit the pixels onto the screen (if the
|
||||
// BinkBuffer is using an off-screen blitting style).
|
||||
//
|
||||
|
||||
BinkBufferBlit( bink_buffer,
|
||||
bink->FrameRects,
|
||||
BinkGetRects( bink, bink_buffer->SurfaceType ) );
|
||||
|
||||
//
|
||||
// Are we at the end of the movie?
|
||||
//
|
||||
|
||||
if ( bink->FrameNum == bink->Frames )
|
||||
{
|
||||
//
|
||||
// Yup, close the window.
|
||||
//
|
||||
|
||||
DestroyWindow( window );
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Nope, advance to the next frame.
|
||||
//
|
||||
|
||||
BinkNextFrame( bink );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## Good_sleep_us - sleeps for a specified number of MICROseconds. ##
|
||||
//## The task switcher in Windows has a latency of 15 ms. That means ##
|
||||
//## you can ask for a Sleep of one millisecond and actually get a ##
|
||||
//## sleep of 15 ms! In normal applications, this is no big deal, ##
|
||||
//## however, with a video player at 30 fps, 15 ms is almost half our ##
|
||||
//## frame time! The Good_sleep_us function times each sleep and keeps ##
|
||||
//## the average sleep time to what you requested. It also give more ##
|
||||
//## accuracy than Sleep - Good_sleep_us() uses microseconds instead of ##
|
||||
//## milliseconds. ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
static void Good_sleep_us( S32 microseconds )
|
||||
{
|
||||
static S32 total_sleep=0;
|
||||
static S32 slept_in_advance=0;
|
||||
static U64 frequency=1000;
|
||||
static S32 got_frequency=0;
|
||||
|
||||
//
|
||||
// If this is the first time called, get the high-performance timer count.
|
||||
//
|
||||
|
||||
if ( !got_frequency )
|
||||
{
|
||||
got_frequency = 1;
|
||||
QueryPerformanceFrequency( ( LARGE_INTEGER* )&frequency );
|
||||
}
|
||||
|
||||
total_sleep += microseconds;
|
||||
|
||||
//
|
||||
// Have we exceeded our reserve of slept microseconds?
|
||||
//
|
||||
|
||||
if (( total_sleep - slept_in_advance ) > 1000)
|
||||
{
|
||||
U64 start, end;
|
||||
total_sleep -= slept_in_advance;
|
||||
|
||||
//
|
||||
// Do the timed sleep.
|
||||
//
|
||||
|
||||
QueryPerformanceCounter( ( LARGE_INTEGER* )&start );
|
||||
Sleep( total_sleep / 1000 );
|
||||
QueryPerformanceCounter( ( LARGE_INTEGER* )&end );
|
||||
|
||||
//
|
||||
// Calculate delta time in microseconds.
|
||||
//
|
||||
|
||||
end = ( (end - start) * (U64)1000000 ) / frequency;
|
||||
|
||||
//
|
||||
// Keep track of how much extra we slept.
|
||||
//
|
||||
|
||||
slept_in_advance = ( U32 )end - total_sleep;
|
||||
total_sleep %= 1000;
|
||||
}
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//## ##
|
||||
//## WinMain - the primary function entry point ##
|
||||
//## ##
|
||||
//############################################################################
|
||||
|
||||
int PASCAL WinMain( HINSTANCE instance,
|
||||
HINSTANCE previous_instance,
|
||||
LPSTR cmd_line,
|
||||
int cmd_show )
|
||||
{
|
||||
//
|
||||
// Win32 locals.
|
||||
//
|
||||
|
||||
HWND window = 0;
|
||||
MSG msg;
|
||||
|
||||
//
|
||||
// Try to create our window.
|
||||
//
|
||||
|
||||
window = Build_window_handle( instance,
|
||||
previous_instance );
|
||||
if ( !window )
|
||||
{
|
||||
MessageBox( 0,
|
||||
"Error creating window.",
|
||||
"Windows",
|
||||
MB_OK | MB_ICONSTOP );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
//
|
||||
// Tell Bink to use DirectSound (must be before BinkOpen)!
|
||||
//
|
||||
|
||||
BinkSoundUseDirectSound( 0 );
|
||||
|
||||
//
|
||||
// Try to open the Bink file.
|
||||
//
|
||||
|
||||
Bink = BinkOpen( cmd_line, 0 );
|
||||
if ( !Bink )
|
||||
{
|
||||
MessageBox( window,
|
||||
BinkGetError( ),
|
||||
"Bink Error",
|
||||
MB_OK | MB_ICONSTOP );
|
||||
|
||||
DestroyWindow( window );
|
||||
return( 3 );
|
||||
}
|
||||
|
||||
//
|
||||
// Try to open the Bink buffer.
|
||||
//
|
||||
|
||||
Bink_buffer = BinkBufferOpen( window, Bink->Width, Bink->Height, 0 );
|
||||
if ( !Bink_buffer )
|
||||
{
|
||||
MessageBox( window,
|
||||
BinkBufferGetError( ),
|
||||
"Bink Error",
|
||||
MB_OK | MB_ICONSTOP );
|
||||
|
||||
DestroyWindow( window );
|
||||
BinkClose( Bink );
|
||||
|
||||
return( 4 );
|
||||
}
|
||||
|
||||
//
|
||||
// Size the window such that its client area exactly fits our Bink movie.
|
||||
//
|
||||
|
||||
SetWindowPos( window, 0,
|
||||
0, 0,
|
||||
Bink_buffer->WindowWidth,
|
||||
Bink_buffer->WindowHeight,
|
||||
SWP_NOMOVE );
|
||||
|
||||
//
|
||||
// Now display the window and start the message loop.
|
||||
//
|
||||
|
||||
ShowWindow( window, cmd_show );
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
//
|
||||
// Are there any messages to handle?
|
||||
//
|
||||
|
||||
if ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
|
||||
{
|
||||
//
|
||||
// Yup, handle them.
|
||||
//
|
||||
|
||||
if ( msg.message == WM_QUIT )
|
||||
break;
|
||||
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Is it time for a new Bink frame?
|
||||
//
|
||||
|
||||
if ( !BinkWait( Bink ) )
|
||||
{
|
||||
//
|
||||
// Yup, draw the next frame.
|
||||
//
|
||||
|
||||
Show_next_frame( Bink,
|
||||
Bink_buffer,
|
||||
window );
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Nope, give the rest of the system a chance to run (500 MICROseconds).
|
||||
//
|
||||
|
||||
Good_sleep_us( 500 );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Close the Bink file.
|
||||
//
|
||||
|
||||
if ( Bink )
|
||||
{
|
||||
BinkClose( Bink );
|
||||
Bink = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Close the Bink buffer.
|
||||
//
|
||||
|
||||
if ( Bink_buffer )
|
||||
{
|
||||
BinkBufferClose( Bink_buffer );
|
||||
Bink_buffer = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// And exit.
|
||||
//
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
// some stuff for the RAD build utility
|
||||
// @cdep pre $DefaultsWinEXE
|
||||
// @cdep pre $requiresbinary($BuildDir/binkw32.lib)
|
||||
// @cdep post $BuildWinEXE( , )
|
||||
Reference in New Issue
Block a user