//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
# include "filesystem.h"
# include "tier1/strtools.h"
# include "tier1/utllinkedlist.h"
# include "tier1/KeyValues.h"
# include "materialsystem/imaterial.h"
# include "materialsystem/imaterialsystem.h"
# include "materialsystem/MaterialSystemUtil.h"
# include "materialsystem/itexture.h"
# include "vgui/ILocalize.h"
# include "vtf/vtf.h"
# include "pixelwriter.h"
# include "tier3/tier3.h"
# include "platform.h"
# include "videoservices.h"
# include "video_macros.h"
# include "tier0/memdbgon.h"
# if defined( WIN32 )
# include <windows.h>
# elif defined( OSX )
# include <Carbon/Carbon.h>
# endif
# if defined( USE_SDL )
# include "SDL.h"
# include "appframework/ilaunchermgr.h"
# endif
//-----------------------------------------------------------------------------
// Platform specific video system controls & definitions
//-----------------------------------------------------------------------------
enum EPlatform_t
{
PLATFORM_NONE = 0 ,
PLATFORM_WIN32 = 0x01 ,
PLATFORM_OSX = 0x02 ,
PLATFORM_XBOX_360 = 0x04 ,
PLATFORM_PS3 = 0x08 ,
PLATFORM_LINUX = 0x10
} ;
DEFINE_ENUM_BITWISE_OPERATORS ( EPlatform_t ) ;
# if defined( IS_WINDOWS_PC )
const EPlatform_t thisPlatform = PLATFORM_WIN32 ;
# elif defined( OSX )
const EPlatform_t thisPlatform = PLATFORM_OSX ;
# elif defined( _X360 )
const EPlatform_t thisPlatform = PLATFORM_XBOX_360 ;
# elif defined( _PS3 )
const EPlatform_t thisPlatform = PLATFORM_PS3 ;
# elif defined ( _LINUX ) || defined(PLATFORM_BSD)
const EPlatform_t thisPlatform = PLATFORM_LINUX ;
# else
# error "UNABLE TO DETERMINE PLATFORM"
# endif
# if defined( OSX ) || defined( LINUX ) || defined(PLATFORM_BSD)
ILauncherMgr * g_pLauncherMgr = NULL ;
# endif
struct VideoSystemInfo_t
{
VideoSystem_t m_SystemID ;
EPlatform_t m_Platforms ;
const char * m_pModuleName ;
const char * m_pInterfaceName ;
} ;
static VideoSystemInfo_t s_VideoAppSystems [ ] =
{
{ VideoSystem : : QUICKTIME , PLATFORM_WIN32 | PLATFORM_OSX , " video_quicktime " , VIDEO_SUBSYSTEM_INTERFACE_VERSION } ,
{ VideoSystem : : BINK , PLATFORM_WIN32 | PLATFORM_OSX | PLATFORM_XBOX_360 | PLATFORM_LINUX , " video_bink " , VIDEO_SUBSYSTEM_INTERFACE_VERSION } ,
//{ VideoSystem::AVI, PLATFORM_WIN32, "avi", VIDEO_SUBSYSTEM_INTERFACE_VERSION },
//{ VideoSystem::WMV, PLATFORM_WIN32, "wmv", VIDEO_SUBSYSTEM_INTERFACE_VERSION },
{ VideoSystem : : WEBM , PLATFORM_LINUX , " video_webm " , VIDEO_SUBSYSTEM_INTERFACE_VERSION } ,
{ VideoSystem : : NONE , PLATFORM_NONE , nullptr , nullptr } // Required to terminate the list
} ;
//-----------------------------------------------------------------------------
// Setup Singleton for accessing Valve Video Services
//-----------------------------------------------------------------------------
static CValveVideoServices g_VALVeVIDEO ;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CValveVideoServices , IVideoServices , VIDEO_SERVICES_INTERFACE_VERSION , g_VALVeVIDEO ) ;
static CVideoCommonServices g_VALVEVIDEOCommon ;
//-----------------------------------------------------------------------------
// Valve Video Services implementation
//-----------------------------------------------------------------------------
CValveVideoServices : : CValveVideoServices ( ) :
m_nInstalledSystems ( 0 ) ,
m_bInitialized ( false ) ,
m_nMaterialCount ( 0 )
{
for ( int i = 0 ; i < VideoSystem : : VIDEO_SYSTEM_COUNT ; i + + )
{
m_VideoSystemModule [ i ] = nullptr ;
m_VideoSystems [ i ] = nullptr ;
m_VideoSystemType [ i ] = VideoSystem : : NONE ;
m_VideoSystemFeatures [ i ] = VideoSystemFeature : : NO_FEATURES ;
}
}
CValveVideoServices : : ~ CValveVideoServices ( )
{
DisconnectVideoLibraries ( ) ;
}
bool CValveVideoServices : : Connect ( CreateInterfaceFn factory )
{
if ( ! BaseClass : : Connect ( factory ) )
{
return false ;
}
if ( g_pFullFileSystem = = nullptr | | materials = = nullptr )
{
Msg ( " Valve Video Services unable to connect due to missing dependent system \n " ) ;
return false ;
}
# if defined( USE_SDL )
g_pLauncherMgr = ( ILauncherMgr * ) factory ( SDLMGR_INTERFACE_VERSION , NULL ) ;
# endif
if ( ! ConnectVideoLibraries ( factory ) )
{
return false ;
}
return ( true ) ;
}
void CValveVideoServices : : Disconnect ( )
{
DisconnectVideoLibraries ( ) ;
}
void * CValveVideoServices : : QueryInterface ( const char * pInterfaceName )
{
if ( Q_strncmp ( pInterfaceName , VIDEO_SERVICES_INTERFACE_VERSION , Q_strlen ( VIDEO_SERVICES_INTERFACE_VERSION ) + 1 ) = = 0 )
{
return ( IVideoServices * ) this ;
}
return nullptr ;
}
bool CValveVideoServices : : ConnectVideoLibraries ( CreateInterfaceFn factory )
{
// Don't connect twice..
AssertExitF ( m_bInitialized = = false ) ;
int n = 0 ;
while ( IS_NOT_EMPTY ( s_VideoAppSystems [ n ] . m_pModuleName ) & & s_VideoAppSystems [ n ] . m_SystemID ! = VideoSystem : : NONE )
{
if ( BITFLAGS_SET ( s_VideoAppSystems [ n ] . m_Platforms , thisPlatform ) )
{
bool success = false ;
CSysModule * pModule = Sys_LoadModule ( s_VideoAppSystems [ n ] . m_pModuleName ) ;
if ( pModule ! = nullptr )
{
CreateInterfaceFn fn = Sys_GetFactory ( pModule ) ;
if ( fn ! = nullptr )
{
IVideoSubSystem * pVideoSystem = ( IVideoSubSystem * ) fn ( s_VideoAppSystems [ n ] . m_pInterfaceName , NULL ) ;
if ( pVideoSystem ! = nullptr & & pVideoSystem - > Connect ( factory ) )
{
if ( pVideoSystem - > InitializeVideoSystem ( & g_VALVEVIDEOCommon ) )
{
int slotNum = ( int ) pVideoSystem - > GetSystemID ( ) ;
if ( IS_IN_RANGECOUNT ( slotNum , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) )
{
Assert ( m_VideoSystemModule [ slotNum ] = = nullptr ) ;
m_VideoSystemModule [ slotNum ] = pModule ;
m_VideoSystems [ slotNum ] = pVideoSystem ;
m_nInstalledSystems + + ;
success = true ;
}
}
}
}
if ( success = = false )
{
Msg ( " Error occurred while attempting to load and initialize Video Subsystem \n Video Subsystem module '%s' \n Video Subsystem Interface '%s' " , s_VideoAppSystems [ n ] . m_pModuleName , s_VideoAppSystems [ n ] . m_pInterfaceName ) ;
Sys_UnloadModule ( pModule ) ;
}
}
}
n + + ;
}
// now we query each video system for its capabilities, and supported file extensions
for ( int i = VideoSystem : : VIDEO_SYSTEM_FIRST ; i < VideoSystem : : VIDEO_SYSTEM_COUNT ; i + + )
{
IVideoSubSystem * pSubSystem = m_VideoSystems [ i ] ;
if ( pSubSystem ! = nullptr )
{
m_VideoSystemType [ i ] = pSubSystem - > GetSystemID ( ) ;
m_VideoSystemFeatures [ i ] = pSubSystem - > GetSupportedFeatures ( ) ;
// get every file extension it handles, and the info about it
int eCount = pSubSystem - > GetSupportedFileExtensionCount ( ) ;
Assert ( eCount > 0 ) ;
for ( int n = 0 ; n < eCount ; n + + )
{
VideoFileExtensionInfo_t extInfoRec ;
extInfoRec . m_FileExtension = pSubSystem - > GetSupportedFileExtension ( n ) ;
extInfoRec . m_VideoSubSystem = pSubSystem - > GetSystemID ( ) ;
extInfoRec . m_VideoFeatures = pSubSystem - > GetSupportedFileExtensionFeatures ( n ) ;
AssertPtr ( extInfoRec . m_FileExtension ) ;
m_ExtInfo . AddToTail ( extInfoRec ) ;
}
}
}
m_bInitialized = true ;
return true ;
}
bool CValveVideoServices : : DisconnectVideoLibraries ( )
{
if ( ! m_bInitialized )
{
return false ;
}
// free up any objects/resources still out there
DestroyAllVideoInterfaces ( ) ;
for ( int i = 0 ; i < VideoSystem : : VIDEO_SYSTEM_COUNT ; i + + )
{
if ( m_VideoSystems [ i ] ! = nullptr )
{
m_VideoSystems [ i ] - > ShutdownVideoSystem ( ) ;
m_VideoSystems [ i ] - > Disconnect ( ) ;
m_VideoSystems [ i ] = nullptr ;
}
if ( m_VideoSystemModule [ i ] ! = nullptr )
{
Sys_UnloadModule ( m_VideoSystemModule [ i ] ) ;
m_VideoSystemModule [ i ] = nullptr ;
}
m_VideoSystemType [ i ] = VideoSystem : : NONE ;
m_VideoSystemFeatures [ i ] = VideoSystemFeature : : NO_FEATURES ;
}
m_bInitialized = false ;
return true ;
}
int CValveVideoServices : : DestroyAllVideoInterfaces ( )
{
int n = m_RecorderList . Count ( ) + m_MaterialList . Count ( ) ;
for ( int i = m_RecorderList . Count ( ) - 1 ; i > = 0 ; i - - )
{
DestroyVideoRecorder ( ( IVideoRecorder * ) m_RecorderList [ i ] . m_pObject ) ;
}
for ( int i = m_MaterialList . Count ( ) - 1 ; i > = 0 ; i - - )
{
DestroyVideoMaterial ( ( IVideoMaterial * ) m_MaterialList [ i ] . m_pObject ) ;
}
return n ;
}
InitReturnVal_t CValveVideoServices : : Init ( )
{
InitReturnVal_t nRetVal = BaseClass : : Init ( ) ;
if ( nRetVal ! = INIT_OK )
{
return nRetVal ;
}
// Initialize all loaded subsystems
for ( int n = VideoSystem : : VIDEO_SYSTEM_FIRST ; n < VideoSystem : : VIDEO_SYSTEM_COUNT ; n + + )
{
if ( m_VideoSystems [ n ] ! = nullptr )
{
nRetVal = m_VideoSystems [ n ] - > Init ( ) ;
if ( nRetVal ! = INIT_OK )
{
return nRetVal ;
}
}
}
return INIT_OK ;
}
void CValveVideoServices : : Shutdown ( )
{
DestroyAllVideoInterfaces ( ) ;
// Shutdown all loaded subsystems
for ( int n = VideoSystem : : VIDEO_SYSTEM_FIRST ; n < VideoSystem : : VIDEO_SYSTEM_COUNT ; n + + )
{
if ( m_VideoSystems [ n ] ! = nullptr )
{
m_VideoSystems [ n ] - > Shutdown ( ) ;
}
}
BaseClass : : Shutdown ( ) ;
}
// ===========================================================================
// Inherited from IVideoServices
// ===========================================================================
// Query the available video systems
int CValveVideoServices : : GetAvailableVideoSystemCount ( )
{
return m_nInstalledSystems ;
}
// returns the enumerated video system, *IF* it is installed and working
VideoSystem_t CValveVideoServices : : GetAvailableVideoSystem ( int n )
{
if ( n < 0 | | n > = m_nInstalledSystems )
{
return VideoSystem : : NONE ;
}
for ( int i = VideoSystem : : VIDEO_SYSTEM_FIRST , c = 0 ; i < VideoSystem : : VIDEO_SYSTEM_COUNT ; i + + )
{
if ( m_VideoSystems [ i ] ! = nullptr )
{
if ( c = = n )
{
return m_VideoSystemType [ i ] ;
}
c + + ;
}
}
return VideoSystem : : NONE ;
}
// ===========================================================================
// returns the index for the video system...
// ... provided that system is installed and available to do something
// ===========================================================================
int CValveVideoServices : : GetIndexForSystem ( VideoSystem_t n )
{
if ( n > = VideoSystem : : VIDEO_SYSTEM_FIRST & & n < VideoSystem : : VIDEO_SYSTEM_COUNT & & m_nInstalledSystems > 0 )
{
int i = ( int ) n ;
if ( m_VideoSystems [ i ] ! = nullptr & & m_VideoSystemFeatures [ i ] ! = VideoSystemFeature : : NO_FEATURES )
{
return i ;
}
}
return SYSTEM_NOT_FOUND ;
}
VideoSystem_t CValveVideoServices : : GetSystemForIndex ( int n )
{
if ( n > = VideoSystem : : VIDEO_SYSTEM_FIRST & & n < VideoSystem : : VIDEO_SYSTEM_COUNT & & m_nInstalledSystems > 0 )
{
if ( m_VideoSystems [ n ] ! = nullptr & & m_VideoSystemFeatures [ n ] ! = VideoSystemFeature : : NO_FEATURES )
{
return ( VideoSystem_t ) n ;
}
}
return VideoSystem : : NONE ;
}
// ===========================================================================
// video system query functions
// ===========================================================================
bool CValveVideoServices : : IsVideoSystemAvailable ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
return ( n ! = SYSTEM_NOT_FOUND ) ? true : false ;
}
VideoSystemStatus_t CValveVideoServices : : GetVideoSystemStatus ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
return ( n ! = SYSTEM_NOT_FOUND ) ? m_VideoSystems [ n ] - > GetSystemStatus ( ) : VideoSystemStatus : : NOT_INSTALLED ;
}
VideoSystemFeature_t CValveVideoServices : : GetVideoSystemFeatures ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
return ( n ! = SYSTEM_NOT_FOUND ) ? m_VideoSystemFeatures [ n ] : VideoSystemFeature : : NO_FEATURES ;
}
const char * CValveVideoServices : : GetVideoSystemName ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
return ( n ! = SYSTEM_NOT_FOUND ) ? m_VideoSystems [ n ] - > GetVideoSystemName ( ) : nullptr ;
}
VideoSystem_t CValveVideoServices : : FindNextSystemWithFeature ( VideoSystemFeature_t features , VideoSystem_t startAfter )
{
if ( ( features & VideoSystemFeature : : ALL_VALID_FEATURES ) = = 0 )
{
return VideoSystem : : NONE ;
}
int start = VideoSystem : : VIDEO_SYSTEM_FIRST ;
if ( startAfter ! = VideoSystem : : NONE & & IS_IN_RANGECOUNT ( startAfter , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) )
{
start = ( int ) startAfter ;
}
for ( int i = start ; i < VideoSystem : : VIDEO_SYSTEM_COUNT ; i + + )
{
if ( m_VideoSystems [ i ] ! = nullptr & & BITFLAGS_SET ( m_VideoSystemFeatures [ i ] , features ) )
{
return ( VideoSystem_t ) i ;
}
}
return VideoSystem : : NONE ;
}
// ===========================================================================
// video services status functions
// ===========================================================================
VideoResult_t CValveVideoServices : : GetLastResult ( )
{
return m_LastResult ;
}
VideoResult_t CValveVideoServices : : SetResult ( VideoResult_t resultCode )
{
m_LastResult = resultCode ;
return resultCode ;
}
// ===========================================================================
// deal with video file extensions and video system mappings
// ===========================================================================
int CValveVideoServices : : GetSupportedFileExtensionCount ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
return ( n = = SYSTEM_NOT_FOUND ) ? 0 : m_VideoSystems [ n ] - > GetSupportedFileExtensionCount ( ) ;
}
const char * CValveVideoServices : : GetSupportedFileExtension ( VideoSystem_t videoSystem , int extNum )
{
int n = GetIndexForSystem ( videoSystem ) ;
int c = ( n = = SYSTEM_NOT_FOUND ) ? 0 : m_VideoSystems [ n ] - > GetSupportedFileExtensionCount ( ) ; ;
return ( extNum < 0 | | extNum > = c ) ? nullptr : m_VideoSystems [ n ] - > GetSupportedFileExtension ( extNum ) ;
}
VideoSystemFeature_t CValveVideoServices : : GetSupportedFileExtensionFeatures ( VideoSystem_t videoSystem , int extNum )
{
int n = GetIndexForSystem ( videoSystem ) ;
int c = ( n = = SYSTEM_NOT_FOUND ) ? 0 : m_VideoSystems [ n ] - > GetSupportedFileExtensionCount ( ) ;
return ( extNum < 0 | | extNum > = c ) ? VideoSystemFeature : : NO_FEATURES : m_VideoSystems [ n ] - > GetSupportedFileExtensionFeatures ( extNum ) ;
}
VideoSystem_t CValveVideoServices : : LocateVideoSystemForPlayingFile ( const char * pFileName , VideoSystemFeature_t playMode )
{
SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( IS_NOT_EMPTY ( pFileName ) , VideoSystem : : NONE ) ;
VideoSystem_t theSystem = LocateSystemAndFeaturesForFileName ( pFileName , nullptr , playMode ) ;
SetResult ( VideoResult : : SUCCESS ) ;
return theSystem ;
}
// ===========================================================================
// Given a video file name, possibly with a set extension, locate the file
// or a suitable substitute that is playable on the current system
// ===========================================================================
VideoResult_t CValveVideoServices : : LocatePlayableVideoFile ( const char * pSearchFileName , const char * pPathID , VideoSystem_t * pPlaybackSystem , char * pPlaybackFileName , int fileNameMaxLen , VideoSystemFeature_t playMode )
{
AssertExitV ( IS_NOT_EMPTY ( pSearchFileName ) | | pPlaybackSystem = = nullptr | | pPlaybackSystem = = nullptr | | fileNameMaxLen < = 0 , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
VideoResult_t Status = ResolveToPlayableVideoFile ( pSearchFileName , pPathID , VideoSystem : : DETERMINE_FROM_FILE_EXTENSION , playMode ,
true , pPlaybackFileName , fileNameMaxLen , pPlaybackSystem ) ;
return SetResult ( Status ) ;
}
// ===========================================================================
// Create/destroy a video material
// ===========================================================================
IVideoMaterial * CValveVideoServices : : CreateVideoMaterial ( const char * pMaterialName , const char * pVideoFileName , const char * pPathID , VideoPlaybackFlags_t playbackFlags , VideoSystem_t videoSystem , bool PlayAlternateIfNotAvailable )
{
SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( IS_NOT_EMPTY ( pVideoFileName ) , nullptr ) ;
AssertExitV ( videoSystem = = VideoSystem : : DETERMINE_FROM_FILE_EXTENSION | | IS_IN_RANGECOUNT ( videoSystem , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) , nullptr ) ;
// We need to resolve the filename and video system
char ResolvedFilePath [ MAX_PATH ] ;
VideoSystem_t actualVideoSystem = videoSystem ;
VideoResult_t Status = ResolveToPlayableVideoFile ( pVideoFileName , pPathID , videoSystem , VideoSystemFeature : : PLAY_VIDEO_FILE_IN_MATERIAL , PlayAlternateIfNotAvailable ,
ResolvedFilePath , sizeof ( ResolvedFilePath ) , & actualVideoSystem ) ;
SetResult ( Status ) ;
if ( Status ! = VideoResult : : SUCCESS )
{
return nullptr ;
}
int sysIndex = GetIndexForSystem ( actualVideoSystem ) ;
if ( sysIndex = = SYSTEM_NOT_FOUND )
{
SetResult ( VideoResult : : SYSTEM_ERROR_OCCURED ) ;
return nullptr ;
}
// Create the video material
IVideoMaterial * pMaterial = m_VideoSystems [ sysIndex ] - > CreateVideoMaterial ( pMaterialName , ResolvedFilePath , playbackFlags ) ;
// Update our list, and return
if ( pMaterial ! = nullptr )
{
CActiveVideoObjectRecord_t info ;
info . m_pObject = pMaterial ;
info . m_VideoSystem = sysIndex ;
m_MaterialList . AddToTail ( info ) ;
}
SetResult ( m_VideoSystems [ sysIndex ] - > GetLastResult ( ) ) ;
return pMaterial ;
}
VideoResult_t CValveVideoServices : : DestroyVideoMaterial ( IVideoMaterial * pVideoMaterial )
{
AssertPtrExitV ( pVideoMaterial , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
for ( int i = 0 ; i < m_MaterialList . Count ( ) ; i + + )
{
if ( m_MaterialList [ i ] . m_pObject = = pVideoMaterial )
{
VideoResult_t Status = m_VideoSystems [ m_MaterialList [ i ] . m_VideoSystem ] - > DestroyVideoMaterial ( pVideoMaterial ) ;
m_MaterialList . Remove ( i ) ;
return SetResult ( Status ) ;
}
}
return SetResult ( VideoResult : : RECORDER_NOT_FOUND ) ;
return VideoResult : : SUCCESS ;
}
int CValveVideoServices : : GetUniqueMaterialID ( )
{
m_nMaterialCount + + ;
return m_nMaterialCount ;
}
// ===========================================================================
// Query availabilily of codec for encoding video
// ===========================================================================
VideoResult_t CValveVideoServices : : IsRecordCodecAvailable ( VideoSystem_t videoSystem , VideoEncodeCodec_t codec )
{
AssertExitV ( codec > = VideoEncodeCodec : : DEFAULT_CODEC & & codec < VideoEncodeCodec : : CODEC_COUNT , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
int n = GetIndexForSystem ( videoSystem ) ;
if ( n = = SYSTEM_NOT_FOUND )
{
return SetResult ( VideoResult : : SYSTEM_NOT_AVAILABLE ) ;
}
return m_VideoSystems [ n ] - > CheckCodecAvailability ( codec ) ;
}
// ===========================================================================
// Create/destroy a video encoder
// ===========================================================================
IVideoRecorder * CValveVideoServices : : CreateVideoRecorder ( VideoSystem_t videoSystem )
{
int n = GetIndexForSystem ( videoSystem ) ;
if ( n = = SYSTEM_NOT_FOUND )
{
SetResult ( VideoResult : : SYSTEM_NOT_AVAILABLE ) ;
return nullptr ;
}
if ( ! BITFLAGS_SET ( m_VideoSystemFeatures [ n ] , VideoSystemFeature : : ENCODE_VIDEO_TO_FILE ) )
{
SetResult ( VideoResult : : FEATURE_NOT_AVAILABLE ) ;
return nullptr ;
}
IVideoRecorder * pRecorder = m_VideoSystems [ n ] - > CreateVideoRecorder ( ) ;
if ( pRecorder ! = nullptr )
{
CActiveVideoObjectRecord_t info ;
info . m_pObject = pRecorder ;
info . m_VideoSystem = n ;
m_RecorderList . AddToTail ( info ) ;
}
SetResult ( m_VideoSystems [ n ] - > GetLastResult ( ) ) ;
return pRecorder ;
}
VideoResult_t CValveVideoServices : : DestroyVideoRecorder ( IVideoRecorder * pVideoRecorder )
{
AssertPtrExitV ( pVideoRecorder , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
for ( int i = 0 ; i < m_RecorderList . Count ( ) ; i + + )
{
if ( m_RecorderList [ i ] . m_pObject = = pVideoRecorder )
{
VideoResult_t Status = m_VideoSystems [ m_RecorderList [ i ] . m_VideoSystem ] - > DestroyVideoRecorder ( pVideoRecorder ) ;
m_RecorderList . Remove ( i ) ;
return SetResult ( Status ) ;
}
}
return SetResult ( VideoResult : : RECORDER_NOT_FOUND ) ;
}
// ===========================================================================
// Plays a given video file until it completes or the user aborts
// ===========================================================================
VideoResult_t CValveVideoServices : : PlayVideoFileFullScreen ( const char * pFileName , const char * pPathID , void * mainWindow , int windowWidth , int windowHeight , int desktopWidth , int desktopHeight , bool windowed , float forcedMinTime , VideoPlaybackFlags_t playbackFlags , VideoSystem_t videoSystem , bool PlayAlternateIfNotAvailable )
{
SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( IS_NOT_EMPTY ( pFileName ) , VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( videoSystem = = VideoSystem : : DETERMINE_FROM_FILE_EXTENSION | | IS_IN_RANGECOUNT ( videoSystem , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) , VideoResult : : BAD_INPUT_PARAMETERS ) ;
char ResolvedFilePath [ MAX_PATH ] ;
VideoSystem_t actualVideoSystem = videoSystem ;
VideoResult_t Status = ResolveToPlayableVideoFile ( pFileName , pPathID , videoSystem , VideoSystemFeature : : PLAY_VIDEO_FILE_FULL_SCREEN , PlayAlternateIfNotAvailable ,
ResolvedFilePath , sizeof ( ResolvedFilePath ) , & actualVideoSystem ) ;
if ( Status ! = VideoResult : : SUCCESS )
{
return Status ;
}
int sysIndex = GetIndexForSystem ( actualVideoSystem ) ;
if ( sysIndex ! = SYSTEM_NOT_FOUND )
{
return SetResult ( m_VideoSystems [ sysIndex ] - > PlayVideoFileFullScreen ( ResolvedFilePath , mainWindow , windowWidth , windowHeight , desktopWidth , desktopHeight , windowed , forcedMinTime , playbackFlags ) ) ;
}
else
{
return SetResult ( VideoResult : : SYSTEM_ERROR_OCCURED ) ;
}
}
// ===========================================================================
// Functions to connect sound systems to video systems
// ===========================================================================
VideoResult_t CValveVideoServices : : SoundDeviceCommand ( VideoSoundDeviceOperation_t operation , void * pDevice , void * pData , VideoSystem_t videoSystem )
{
AssertExitV ( IS_IN_RANGECOUNT ( operation , 0 , VideoSoundDeviceOperation : : OPERATION_COUNT ) , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
AssertExitV ( videoSystem = = VideoSystem : : ALL_VIDEO_SYSTEMS | | IS_IN_RANGECOUNT ( videoSystem , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) , SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ) ;
int startIdx = ( int ) VideoSystem : : VIDEO_SYSTEM_FIRST ;
int lastIdx = ( int ) VideoSystem : : VIDEO_SYSTEM_COUNT - 1 ;
if ( videoSystem ! = VideoSystem : : ALL_VIDEO_SYSTEMS )
{
startIdx = lastIdx = GetIndexForSystem ( videoSystem ) ;
if ( startIdx = = SYSTEM_NOT_FOUND )
{
return SetResult ( VideoResult : : SYSTEM_NOT_AVAILABLE ) ;
}
}
VideoResult_t result = VideoResult : : SYSTEM_NOT_AVAILABLE ;
for ( int i = startIdx ; i < = lastIdx ; i + + )
{
int n = GetIndexForSystem ( ( VideoSystem_t ) i ) ;
if ( n ! = SYSTEM_NOT_FOUND )
{
result = m_VideoSystems [ n ] - > VideoSoundDeviceCMD ( operation , pDevice , pData ) ;
}
}
return SetResult ( result ) ;
}
// ===========================================================================
// Sets the sound devices that the video will decode to
// ===========================================================================
const wchar_t * CValveVideoServices : : GetCodecName ( VideoEncodeCodec_t nCodec )
{
static const char * s_pCodecLookup [ VideoEncodeCodec : : CODEC_COUNT ] =
{
" #Codec_MPEG2 " ,
" #Codec_MPEG4 " ,
" #Codec_H261 " ,
" #Codec_H263 " ,
" #Codec_H264 " ,
" #Codec_MJPEG_A " ,
" #Codec_MJPEG_B " ,
" #Codec_SORENSON3 " ,
" #Codec_CINEPACK " ,
" #Codec_WEBM " ,
} ;
if ( nCodec < 0 | | nCodec > = VideoEncodeCodec : : CODEC_COUNT )
{
AssertMsg ( 0 , " Invalid codec in CValveVideoServices::GetCodecName() " ) ;
return NULL ;
}
return g_pVGuiLocalize - > Find ( s_pCodecLookup [ nCodec ] ) ;
}
// ===========================================================================
// Functions to determine which file and video system to use
// ===========================================================================
VideoResult_t CValveVideoServices : : ResolveToPlayableVideoFile ( const char * pFileName , const char * pPathID , VideoSystem_t videoSystem , VideoSystemFeature_t requiredFeature ,
bool PlayAlternateIfNotAvailable , char * pResolvedFileName , int resolvedFileNameMaxLen , VideoSystem_t * pResolvedVideoSystem )
{
SetResult ( VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( IS_NOT_EMPTY ( pFileName ) , VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( videoSystem = = VideoSystem : : DETERMINE_FROM_FILE_EXTENSION | | IS_IN_RANGECOUNT ( videoSystem , VideoSystem : : VIDEO_SYSTEM_FIRST , VideoSystem : : VIDEO_SYSTEM_COUNT ) , VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( requiredFeature ! = VideoSystemFeature : : NO_FEATURES , VideoResult : : BAD_INPUT_PARAMETERS ) ;
AssertExitV ( pResolvedFileName ! = nullptr & & resolvedFileNameMaxLen > 0 & & pResolvedVideoSystem ! = nullptr , VideoResult : : BAD_INPUT_PARAMETERS ) ;
// clear results should we return failure
pResolvedFileName [ 0 ] = nullchar ;
* pResolvedVideoSystem = VideoSystem : : NONE ;
int sysIdx = SYSTEM_NOT_FOUND ;
VideoSystemFeature_t sysFeatures = VideoSystemFeature : : NO_FEATURES ;
// check the file extension to see if it specifies searching for any compatible video files
// if so, override a couple input values
if ( ! IsMatchAnyExtension ( pFileName ) )
{
goto search_for_video ;
}
// is the requested video system available?
// We start with either the specified video system.. OR.. we choose the system based on the file extension
// Get the system and if it's valid, it's available features
if ( videoSystem ! = VideoSystem : : DETERMINE_FROM_FILE_EXTENSION )
{
sysIdx = GetIndexForSystem ( videoSystem ) ; // Caller specified the video system
sysFeatures = ( sysIdx ! = SYSTEM_NOT_FOUND ) ? m_VideoSystemFeatures [ sysIdx ] : VideoSystemFeature : : NO_FEATURES ;
}
else
{
// We need to determine the system to use based on filename
sysIdx = GetIndexForSystem ( LocateSystemAndFeaturesForFileName ( pFileName , & sysFeatures , requiredFeature ) ) ;
}
// if we don't have a system to play this video.. and aren't allowed to look for an alternative...
if ( sysIdx = = SYSTEM_NOT_FOUND & & PlayAlternateIfNotAvailable = = false )
{
return SetResult ( VideoResult : : VIDEO_SYSTEM_NOT_FOUND ) ; // return failure
}
char ActualFilePath [ MAX_PATH ] ;
// Examine the requested of inferred video system to see if it can do what we want,
// and if so, see if the corresponding file is actually found (we support search paths)
// Decision Path for when we have a preferred/specified video system specified to use
if ( sysIdx ! = SYSTEM_NOT_FOUND )
{
bool fileFound = false ;
// if the request system can do the task, see if we can find the file as supplied by the caller
if ( BITFLAGS_SET ( sysFeatures , requiredFeature ) )
{
if ( V_IsAbsolutePath ( pFileName ) )
{
V_strncpy ( ActualFilePath , pFileName , sizeof ( ActualFilePath ) ) ;
fileFound = g_pFullFileSystem - > FileExists ( pFileName , nullptr ) ;
}
else
{
fileFound = ( g_pFullFileSystem - > RelativePathToFullPath ( pFileName , pPathID , ActualFilePath , sizeof ( ActualFilePath ) ) ! = nullptr ) ;
}
}
else // The specified video system does not support this (required) feature
{
// if we can't search for an alternative file, tell them we don't support this
if ( ! PlayAlternateIfNotAvailable )
{
return SetResult ( VideoResult : : FEATURE_NOT_AVAILABLE ) ;
}
}
// We found the specified file, and the video system has the feature support
if ( fileFound )
{
// copy the resolved filename and system and report success
V_strncpy ( pResolvedFileName , ActualFilePath , resolvedFileNameMaxLen ) ;
* pResolvedVideoSystem = GetSystemForIndex ( sysIdx ) ;
return SetResult ( VideoResult : : SUCCESS ) ;
}
// ok, we have the feature support but didn't find the file to use...
if ( ! PlayAlternateIfNotAvailable )
{
// if we can't search for an alternate file, so report file not found
return SetResult ( VideoResult : : VIDEO_FILE_NOT_FOUND ) ;
}
}
// Ok, we didn't find the file and a system that could handle it
// but hey, we are allowed to look for an alternate video file and system
search_for_video :
// start with the passed in filespec, and change the extension to wildcard
char SearchFileSpec [ MAX_PATH ] ;
V_strncpy ( SearchFileSpec , pFileName , sizeof ( SearchFileSpec ) ) ;
V_SetExtension ( SearchFileSpec , " .* " , sizeof ( SearchFileSpec ) ) ;
FileFindHandle_t searchHandle = 0 ;
const char * pMatchingFile = g_pFullFileSystem - > FindFirstEx ( SearchFileSpec , pPathID , & searchHandle ) ;
while ( pMatchingFile ! = nullptr )
{
const char * pExt = GetFileExtension ( pMatchingFile ) ;
if ( pExt ! = nullptr )
{
// compare file extensions
for ( int i = 0 ; i < m_ExtInfo . Count ( ) ; i + + )
{
// do we match a known extension?
if ( stricmp ( pExt , m_ExtInfo [ i ] . m_FileExtension ) = = STRINGS_MATCH )
{
// do we support the requested feature?
if ( BITFLAGS_SET ( m_ExtInfo [ i ] . m_VideoFeatures , requiredFeature ) )
{
// Make sure it's a valid system
sysIdx = GetIndexForSystem ( m_ExtInfo [ i ] . m_VideoSubSystem ) ;
if ( sysIdx ! = SYSTEM_NOT_FOUND )
{
// Start with any optional path we got...
V_ExtractFilePath ( pFileName , ActualFilePath , sizeof ( ActualFilePath ) ) ;
// Append the search match file
V_strncat ( ActualFilePath , pMatchingFile , sizeof ( ActualFilePath ) ) ;
if ( V_IsAbsolutePath ( ActualFilePath ) )
{
V_strncpy ( pResolvedFileName , ActualFilePath , resolvedFileNameMaxLen ) ;
}
else
{
g_pFullFileSystem - > RelativePathToFullPath ( ActualFilePath , pPathID , pResolvedFileName , resolvedFileNameMaxLen ) ;
}
// Return the system
* pResolvedVideoSystem = GetSystemForIndex ( sysIdx ) ;
g_pFullFileSystem - > FindClose ( searchHandle ) ;
return SetResult ( VideoResult : : SUCCESS ) ;
}
}
}
}
}
// not usable.. keep searching
pMatchingFile = g_pFullFileSystem - > FindNext ( searchHandle ) ;
}
// we didn't find anything we could use
g_pFullFileSystem - > FindClose ( searchHandle ) ;
return SetResult ( VideoResult : : VIDEO_FILE_NOT_FOUND ) ;
}
VideoSystem_t CValveVideoServices : : LocateSystemAndFeaturesForFileName ( const char * pFileName , VideoSystemFeature_t * pFeatures , VideoSystemFeature_t requiredFeatures )
{
if ( pFeatures ! = nullptr )
{
* pFeatures = VideoSystemFeature : : NO_FEATURES ;
}
AssertExitV ( IS_NOT_EMPTY ( pFileName ) , VideoSystem : : NONE ) ;
if ( m_ExtInfo . Count ( ) < 1 )
{
return VideoSystem : : NONE ;
}
// extract the file extension
char fileExt [ MAX_PATH ] ;
const char * pExt = GetFileExtension ( pFileName ) ;
if ( pExt = = nullptr )
{
return VideoSystem : : NONE ;
}
// lowercase it so we can compare
V_strncpy ( fileExt , pExt , sizeof ( fileExt ) ) ;
V_strlower ( fileExt ) ;
for ( int i = 0 ; i < m_ExtInfo . Count ( ) ; i + + )
{
if ( V_stricmp ( fileExt , m_ExtInfo [ i ] . m_FileExtension ) = = STRINGS_MATCH )
{
// must it have certain feature support?
if ( requiredFeatures ! = VideoSystemFeature : : NO_FEATURES )
{
if ( ! BITFLAGS_SET ( m_ExtInfo [ i ] . m_VideoFeatures , requiredFeatures ) )
{
continue ;
}
}
if ( pFeatures ! = nullptr )
{
* pFeatures = m_ExtInfo [ i ] . m_VideoFeatures ;
}
return m_ExtInfo [ i ] . m_VideoSubSystem ;
}
}
return VideoSystem : : NONE ;
}
bool CValveVideoServices : : IsMatchAnyExtension ( const char * pFileName )
{
if ( IS_EMPTY_STR ( pFileName ) )
{
return false ;
}
const char * pExt = GetFileExtension ( pFileName ) ;
if ( pExt = = nullptr )
{
return false ;
}
return ( V_stricmp ( pExt , FILE_EXTENSION_ANY_MATCHING_VIDEO ) = = STRINGS_MATCH ) ;
}
const char * CValveVideoServices : : GetFileExtension ( const char * pFileName )
{
if ( pFileName = = nullptr )
{
return nullptr ;
}
const char * pExt = V_GetFileExtension ( pFileName ) ;
if ( pExt = = nullptr )
{
return nullptr ;
}
if ( pExt ! = pFileName & & * ( pExt - 1 ) = = ' . ' )
{
pExt - - ;
}
return pExt ;
}
// ===========================================================================
// CVideoCommonServices - services used by any/multiple videoSubsystems
// Functions are put here to avoid duplication and ensure they stay
// consistant across all installed subsystems
// ===========================================================================
# ifdef WIN32
typedef SHORT ( WINAPI * GetAsyncKeyStateFn_t ) ( int vKey ) ;
static HINSTANCE s_UserDLLhInst = nullptr ;
GetAsyncKeyStateFn_t s_pfnGetAsyncKeyState = nullptr ;
# endif
CVideoCommonServices : : CVideoCommonServices ( )
{
ResetInputHandlerState ( ) ;
}
CVideoCommonServices : : ~ CVideoCommonServices ( )
{
if ( m_bInputHandlerInitialized )
{
TerminateFullScreenPlaybackInputHandler ( ) ;
}
}
void CVideoCommonServices : : ResetInputHandlerState ( )
{
m_bInputHandlerInitialized = false ;
m_bScanAll = false ;
m_bScanEsc = false ;
m_bScanReturn = false ;
m_bScanSpace = false ;
m_bPauseEnabled = false ;
m_bAbortEnabled = false ;
m_bEscLast = false ;
m_bReturnLast = false ;
m_bSpaceLast = false ;
m_bForceMinPlayTime = false ;
m_bWindowed = false ;
m_playbackFlags = VideoPlaybackFlags : : NO_PLAYBACK_OPTIONS ;
m_forcedMinTime = 0.0f ;
m_StartTime = 0 ;
# ifdef WIN32
s_UserDLLhInst = nullptr ;
s_pfnGetAsyncKeyState = nullptr ;
# endif
}
// ===========================================================================
// Calculate the proper dimensions to play a video in full screen mode
// uses the playback flags to supply rules for streaching, scaling and
// centering the video
// ===========================================================================
bool CVideoCommonServices : : CalculateVideoDimensions ( int videoWidth , int videoHeight , int displayWidth , int displayHeight , VideoPlaybackFlags_t playbackFlags ,
int * pOutputWidth , int * pOutputHeight , int * pXOffset , int * pYOffset )
{
AssertExitF ( pOutputWidth ! = nullptr & & pOutputHeight ! = nullptr & & pXOffset ! = nullptr & & pYOffset ! = nullptr ) ;
AssertExitF ( videoWidth > = 16 & & videoHeight > = 16 & & displayWidth > 64 & & displayHeight > 64 ) ;
// extract relevant options
bool bFillWindow = BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : FILL_WINDOW ) ;
bool bLockAspect = BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : LOCK_ASPECT_RATIO ) ;
bool bIntegralScale = BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : INTEGRAL_SCALE ) ;
bool bCenterVideo = BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : CENTER_VIDEO_IN_WINDOW ) ;
int curWidth = videoWidth ;
int curHeight = videoHeight ;
// Try and just play it actual size?
if ( ! bFillWindow )
{
// is the window the same size or larger?
if ( curWidth < = displayWidth & & curHeight < = displayHeight )
{
goto finish ;
}
else // we need to shrink the video output
{
// if we aren't locking the aspect ratio, just shrink each axis until it fits
if ( ! bLockAspect )
{
while ( curWidth > displayWidth )
{
curWidth = ( bIntegralScale ) ? curWidth > > 1 : displayWidth ;
}
while ( curHeight > displayHeight )
{
curHeight = ( bIntegralScale ) ? curHeight > > 1 : displayHeight ;
}
goto finish ;
}
else // we are locking the aspect ratio, and need to shrink the video
{
// integral scale only....
if ( bIntegralScale )
{
while ( curWidth > displayWidth | | curHeight > displayHeight )
{
curWidth > > = 1 ;
curHeight > > = 1 ;
}
goto finish ;
}
else // can scale variably..
{
float Xfactor = ( displayWidth / curWidth ) ;
float Yfactor = ( displayHeight / curHeight ) ;
float scale = MIN ( Xfactor , Yfactor ) ;
curWidth = ( int ) ( curWidth * scale + 0.35f ) ;
curHeight = ( int ) ( curHeight * scale + 0.35f ) ;
clamp ( curWidth , 0 , displayWidth ) ;
clamp ( curHeight , 0 , displayHeight ) ;
goto finish ;
}
}
}
}
// ok.. we are wanting to fill the window....
if ( bFillWindow )
{
// are we locking the aspect ratio?
if ( bLockAspect )
{
// are we only allowed to scale integrally?
if ( bIntegralScale )
{
while ( ( curWidth < < 1 ) < = displayWidth & & ( curHeight < < 1 ) < = displayHeight )
{
curWidth < < = 1 ;
curHeight < < = 1 ;
}
goto finish ;
}
else
{
float Xfactor = ( ( float ) displayWidth / curWidth ) ;
float Yfactor = ( ( float ) displayHeight / curHeight ) ;
float scale = MIN ( Xfactor , Yfactor ) ;
curWidth = ( int ) ( curWidth * scale + 0.35f ) ;
curHeight = ( int ) ( curHeight * scale + 0.35f ) ;
clamp ( curWidth , 0 , displayWidth ) ;
clamp ( curHeight , 0 , displayHeight ) ;
goto finish ;
}
}
else // we are not locking the aspect ratio...
{
if ( bIntegralScale )
{
while ( ( curWidth < < 1 ) < = displayWidth )
{
curWidth < < = 1 ;
}
while ( ( curHeight < < 1 ) < = displayHeight )
{
curHeight < < = 1 ;
}
goto finish ;
}
else
{
curWidth = displayWidth ;
curHeight = displayHeight ;
goto finish ;
}
}
}
finish :
AssertExitF ( displayWidth > = curWidth & & displayHeight > = curHeight ) ;
if ( bCenterVideo )
{
* pXOffset = ( displayWidth - curWidth ) > > 1 ;
* pYOffset = ( displayHeight - curHeight ) > > 1 ;
}
else
{
* pXOffset = 0 ;
* pYOffset = 0 ;
}
* pOutputWidth = curWidth ;
* pOutputHeight = curHeight ;
return true ;
}
float CVideoCommonServices : : GetSystemVolume ( )
{
ConVarRef volumeConVar ( " volume " ) ;
float sysVolume = volumeConVar . IsValid ( ) ? volumeConVar . GetFloat ( ) : 1.0f ;
clamp ( sysVolume , 0.0f , 1.0f ) ;
return sysVolume ;
}
// ===========================================================================
// Sets up the state machine to receive messages and poll the keyboard
// while a full-screen video is playing
// ===========================================================================
VideoResult_t CVideoCommonServices : : InitFullScreenPlaybackInputHandler ( VideoPlaybackFlags_t playbackFlags , float forcedMinTime , bool windowed )
{
// already initialized?
if ( m_bInputHandlerInitialized )
{
WarningAssert ( " called twice " ) ;
return VideoResult : : OPERATION_ALREADY_PERFORMED ;
}
# ifdef WIN32
// We need to be able to poll the state of the input device, but we're not completely setup yet, so this spoofs the ability
HINSTANCE m_UserDLLhInst = LoadLibrary ( " user32.dll " ) ;
if ( m_UserDLLhInst = = NULL )
{
return VideoResult : : SYSTEM_ERROR_OCCURED ;
}
s_pfnGetAsyncKeyState = ( GetAsyncKeyStateFn_t ) GetProcAddress ( m_UserDLLhInst , " GetAsyncKeyState " ) ;
if ( s_pfnGetAsyncKeyState = = NULL )
{
FreeLibrary ( m_UserDLLhInst ) ;
return VideoResult : : SYSTEM_ERROR_OCCURED ;
}
# endif
// save off playback options
m_playbackFlags = playbackFlags ;
m_forcedMinTime = forcedMinTime ;
m_bWindowed = windowed ;
// process the pause and abort options
m_bScanAll = ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : PAUSE_ON_ANY_KEY | VideoPlaybackFlags : : ABORT_ON_ANY_KEY ) ;
m_bScanEsc = m_bScanAll | | ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : PAUSE_ON_ESC | VideoPlaybackFlags : : ABORT_ON_ESC ) ;
m_bScanReturn = m_bScanAll | | ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : PAUSE_ON_RETURN | VideoPlaybackFlags : : ABORT_ON_RETURN ) ;
m_bScanSpace = m_bScanAll | | ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : PAUSE_ON_SPACE | VideoPlaybackFlags : : ABORT_ON_SPACE ) ;
m_bPauseEnabled = ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : PAUSE_ON_ESC | VideoPlaybackFlags : : PAUSE_ON_RETURN | VideoPlaybackFlags : : PAUSE_ON_SPACE | VideoPlaybackFlags : : PAUSE_ON_ANY_KEY ) ;
m_bAbortEnabled = ANY_BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : ABORT_ON_ESC | VideoPlaybackFlags : : ABORT_ON_RETURN | VideoPlaybackFlags : : ABORT_ON_SPACE | VideoPlaybackFlags : : ABORT_ON_ANY_KEY ) ;
// Setup the scan options
m_bEscLast = false ;
m_bReturnLast = false ;
m_bSpaceLast = false ;
// Other Movie playback state init
m_bForceMinPlayTime = BITFLAGS_SET ( playbackFlags , VideoPlaybackFlags : : FORCE_MIN_PLAY_TIME ) & & ( forcedMinTime > 0.0f ) ;
// Note the start time
m_StartTime = Plat_FloatTime ( ) ;
// and we're on
m_bInputHandlerInitialized = true ;
return VideoResult : : SUCCESS ;
}
// ===========================================================================
// Pumps the message loops and checks for a supported event
// returns true if there is an event to check
// ===========================================================================
bool CVideoCommonServices : : ProcessFullScreenInput ( bool & bAbortEvent , bool & bPauseEvent , bool & bQuitEvent )
{
bAbortEvent = false ;
bPauseEvent = false ;
bQuitEvent = false ;
if ( ! m_bInputHandlerInitialized )
{
WarningAssert ( " Not Initialized to call " ) ;
return false ;
}
// Pump OS Messages
# if defined( WIN32 )
MSG msg ;
while ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) )
{
// did we get a quit message?
if ( msg . message = = WM_QUIT )
{
: : PostQuitMessage ( msg . wParam ) ;
return true ;
}
// todo - look for alt-tab events, etc?
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
// Escape, return, or space stops or pauses the playback
bool bEscPressed = ( m_bScanEsc ) ? ( s_pfnGetAsyncKeyState ( VK_ESCAPE ) & 0x8000 ) ! = 0 : false ;
bool bReturnPressed = ( m_bScanReturn ) ? ( s_pfnGetAsyncKeyState ( VK_RETURN ) & 0x8000 ) ! = 0 : false ;
bool bSpacePressed = ( m_bScanSpace ) ? ( s_pfnGetAsyncKeyState ( VK_SPACE ) & 0x8000 ) ! = 0 : false ;
# elif defined(OSX)
g_pLauncherMgr - > PumpWindowsMessageLoop ( ) ;
// Escape, return, or space stops or pauses the playback
bool bEscPressed = ( m_bScanEsc ) ? CGEventSourceKeyState ( kCGEventSourceStateCombinedSessionState , kVK_Escape ) : false ;
bool bReturnPressed = ( m_bScanReturn ) ? CGEventSourceKeyState ( kCGEventSourceStateCombinedSessionState , kVK_Return ) : false ;
bool bSpacePressed = ( m_bScanSpace ) ? CGEventSourceKeyState ( kCGEventSourceStateCombinedSessionState , kVK_Space ) : false ;
# elif defined(LINUX) || defined(PLATFORM_BSD)
g_pLauncherMgr - > PumpWindowsMessageLoop ( ) ;
// Escape, return, or space stops or pauses the playback
bool bEscPressed = false ;
bool bReturnPressed = false ;
bool bSpacePressed = false ;
g_pLauncherMgr - > PeekAndRemoveKeyboardEvents ( & bEscPressed , & bReturnPressed , & bSpacePressed ) ;
# endif
// Manual debounce of the keys, only interested in unpressed->pressed transitions
bool bEscEvent = ( bEscPressed ! = m_bEscLast ) & & bEscPressed ;
bool bReturnEvent = ( bReturnPressed ! = m_bReturnLast ) & & bReturnPressed ;
bool bSpaceEvent = ( bSpacePressed ! = m_bSpaceLast ) & & bSpacePressed ;
bool bAnyKeyEvent = bEscEvent | | bReturnEvent | | bSpaceEvent ;
m_bEscLast = bEscPressed ;
m_bReturnLast = bReturnPressed ;
m_bSpaceLast = bSpacePressed ;
// Are we forcing a minimum playback time?
// if so, no Abort or Pause events until the necessary time has elasped
if ( m_bForceMinPlayTime )
{
double elapsedTime = Plat_FloatTime ( ) - m_StartTime ;
if ( ( float ) elapsedTime > m_forcedMinTime )
{
m_bForceMinPlayTime = false ; // turn off forced minimum
}
}
// any key events to check? ( provided minimum enforced playback has occurred )
if ( m_bForceMinPlayTime = = false & & bAnyKeyEvent )
{
// check for aborting the movie
if ( m_bAbortEnabled )
{
bAbortEvent = ( bAnyKeyEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : ABORT_ON_ANY_KEY ) ) | |
( bEscEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : ABORT_ON_ESC ) ) | |
( bReturnEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : ABORT_ON_RETURN ) ) | |
( bSpaceEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : ABORT_ON_SPACE ) ) ;
}
// check for pausing the movie?
if ( m_bPauseEnabled )
{
bPauseEvent = ( bAnyKeyEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : PAUSE_ON_ANY_KEY ) ) | |
( bEscEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : PAUSE_ON_ESC ) ) | |
( bReturnEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : PAUSE_ON_RETURN ) ) | |
( bSpaceEvent & & BITFLAGS_SET ( m_playbackFlags , VideoPlaybackFlags : : PAUSE_ON_SPACE ) ) ;
}
}
// notify if any events triggered
return ( bAbortEvent | | bPauseEvent ) ;
}
VideoResult_t CVideoCommonServices : : TerminateFullScreenPlaybackInputHandler ( )
{
if ( ! m_bInputHandlerInitialized )
{
WarningAssert ( " Not Initialized to call " ) ;
return VideoResult : : OPERATION_OUT_OF_SEQUENCE ;
}
# if defined ( WIN32 )
FreeLibrary ( s_UserDLLhInst ) ; // and free the dll we needed
# endif
ResetInputHandlerState ( ) ;
return VideoResult : : SUCCESS ;
}