PaintAudioWindow(void);
//Проверка на наличие видео данных в файлеCheckVisibility(void);
//Освобождение интерфейсами аппаратных ресурсов
void CloseInterfaces(void);
//Открытие файлаOpenClip(int);
//ПаузаPauseClip(void);
//ОстановкаStopClip(void);
//Закрытие клипаCloseClip(void);Msg(TCHAR *szFormat, ...);
//
// Constants
//
#define VOLUME_FULL 0L
#define VOLUME_SILENCE -10000L
// Begin default media search at root directory
#define DEFAULT_MEDIA_PATH TEXT("\\\0")
// Defaults used with audio-only files
#define DEFAULT_AUDIO_WIDTH 240
#define DEFAULT_AUDIO_HEIGHT 120
#define DEFAULT_VIDEO_WIDTH 320
#define DEFAULT_VIDEO_HEIGHT 240
#define MINIMUM_VIDEO_WIDTH 200
#define MINIMUM_VIDEO_HEIGHT 120
#define WM_GRAPHNOTIFY WM_USER+13PLAYSTATE {Stopped, Paused, Running, Init};
//
// Macros
//
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
#define JIF(x) if (FAILED(hr=(x))) \
{Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n\0"), hr); return hr;}
#define LIF(x) if (FAILED(hr=(x))) \
{Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("\n\0"), hr);}PLAYSTATE g_psCurrent;HWND ghApp;HINSTANCE ghInst;BOOL g_bFullscreen;
}
ПРИЛОЖЕНИЕ 2
Листинг модуля воспроизведения playwnd.cpp на языке С++
#include <dshow.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdio.h>
#include <tchar.h>
#include <atlcore.h>
#include <objbase.h>
#include "playwnd.h"Player
{
//
// Global data
//ghApp=0;ghInst=0;g_szFileName[MAX_PATH]={0};g_bAudioOnly=FALSE, g_bFullscreen=FALSE;g_lVolume=VOLUME_FULL;g_dwGraphRegister=0;g_psCurrent=Stopped;g_PlaybackRate=1.0;
// DirectShow interfaces*pGB = NULL;*pMC = NULL;*pME = NULL;*pVW = NULL;*pBA = NULL;*pBV = NULL;*pMS = NULL;*pMP = NULL;int AUDIO=1, VIDEO=2; // Used for enabling playback menu items
//ЯPlayMovieInWindow(LPTSTR szFile)
{_CONVERSION;wFile[MAX_PATH];hr;(!szFile)E_POINTER;
// Clear open dialog remnants before calling RenderFile()(ghApp);
// Convert filename to wide character string(wFile, T2W(szFile), NUMELMS(wFile)-1);[MAX_PATH-1] = 0;
// Get the interface for DirectShow's GraphBuilder(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, _IGraphBuilder, (void **)&pGB));(SUCCEEDED(hr))
{
// Have the graph builder construct its the appropriate graph automatically(pGB->RenderFile(wFile, NULL));
// QueryInterface for DirectShow interfaces(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS));(pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP));
//// Query for video interfaces, which may not be relevant for audio files(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV));
//// Query for audio interfaces, which may not be relevant for video-only files(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA));
//// Is this an audio-only file (no video component)?();
//// Have the graph signal event via window callbacks for performance(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0));(!g_bAudioOnly)
{
// Setup the video window(pVW->put_Owner((OAHWND)ghApp));(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));(InitVideoWindow(1, 1));
}
{
// Initialize the default player size and enable playback menu items(InitPlayerWindow());
}
// Complete window initialization(ghApp, SW_SHOWNORMAL);(ghApp);(ghApp);_bFullscreen = FALSE;_PlaybackRate = 1.0;
//#ifdef REGISTER_FILTERGRAPH
// hr = AddGraphToRot(pGB, &g_dwGraphRegister);
// {
// Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr);
// g_dwGraphRegister = 0;
// }
//#endif
// Run the graph to play the media file(pMC->Run());_psCurrent=Running;(ghApp);
}hr;
}
//ЯInitVideoWindow(int nMultiplier, int nDivider)
{
//LONG lHeight, lWidth;hr = S_OK;rect;(!pBV)S_OK;
// Read the default video size
//hr = pBV->GetVideoSize(&lWidth, &lHeight);(hr == E_NOINTERFACE)S_OK;
// Account for requests of normal, half, or double size
/*lWidth = lWidth * nMultiplier / nDivider;= lHeight * nMultiplier / nDivider;nTitleHeight = GetSystemMetrics(SM_CYCAPTION);nBorderWidth = GetSystemMetrics(SM_CXBORDER);nBorderHeight = GetSystemMetrics(SM_CYBORDER);*/(ghApp, &rect);
// Account for size of title bar and borders for exact match
// of window client area to default video size(ghApp, NULL, 0, 0, rect.right,rect.bottom,_NOMOVE | SWP_NOOWNERZORDER);(ghApp, &rect);(pVW->SetWindowPosition(rect.left, rect.top, rect.right,rect.bottom));hr;
}
//ЯInitPlayerWindow(void)
{
// Reset to a default size for audio and after closing a clip
/*SetWindowPos(ghApp, NULL, 0, 0,_AUDIO_WIDTH,_AUDIO_HEIGHT,_NOMOVE | SWP_NOOWNERZORDER);*/
// Check the 'full size' menu item
// CheckSizeMenu(ID_FILE_SIZE_NORMAL);
// EnablePlaybackMenu(FALSE, 0);S_OK;
}CheckVisibility(void)
{lVisible;hr;((!pVW) || (!pBV))
{
// Audio-only files have no video interfaces. This might also
// be a file whose video component uses an unknown video codec._bAudioOnly = TRUE;;
}
{
// Clear the global flag_bAudioOnly = FALSE;
}= pVW->get_Visible(&lVisible);(FAILED(hr))
{
// If this is an audio-only clip, get_Visible() won't work.
//
// Also, if this video is encoded with an unsupported codec,
// we won't see any video, although the audio will work if it is
// of a supported format.
//(hr == E_NOINTERFACE)
{_bAudioOnly = TRUE;
}
{(TEXT("Failed(%08lx) in pVW->get_Visible()!\r\n"), hr);
}
}
}PauseClip(void)
{(!pMC);
// Toggle play/pause behavior((g_psCurrent == Paused) || (g_psCurrent == Stopped))
{(SUCCEEDED(pMC->Run()))_psCurrent = Running;
}
{(SUCCEEDED(pMC->Pause()))_psCurrent = Paused;
}
}StopClip(void)
{hr;((!pMC) || (!pMS));
// Stop and reset postion to beginning((g_psCurrent == Paused) || (g_psCurrent == Running))
{pos = 0;= pMC->Stop();_psCurrent = Stopped;
// Seek to the beginning= pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,, AM_SEEKING_NoPositioning);
// Display the first frame to indicate the reset condition= pMC->Pause();
}
}
//ЯOpenClip(int clip)
{hr;
// Reset status variables_psCurrent = Stopped;_lVolume = VOLUME_FULL;(MAX_PATH,g_szFileName);file;(clip)
{1:file=_tcscat(g_szFileName,_T("\\clip1.avi"));break;2:file=_tcscat(g_szFileName,_T("\\clip2.avi"));break;3:file=_tcscat(g_szFileName,_T("\\clip3.avi"));break;4:file=_tcscat(g_szFileName,_T("\\clip4.avi"));break;
}
// Start playing the media file= PlayMovieInWindow(file);
// If we couldn't play the clip, clean up(FAILED(hr))();
}CloseClip()
{hr;
// Clear global flags_psCurrent = Stopped;_bAudioOnly = TRUE;_bFullscreen = FALSE;
// Free DirectShow interfaces();
// Clear file name to allow selection of new file with open dialog_szFileName[0] = L'\0';
// No current media state_psCurrent = Init;
// Reset the player windowrect;(ghApp, &rect);(ghApp, &rect, TRUE);();
}CloseInterfaces(void)
{hr;
// Relinquish ownership (IMPORTANT!) after hiding video window(pVW)
{= pVW->put_Visible(OAFALSE);= pVW->put_Owner(NULL);
}
// Disable event callbacks(pME)= pME->SetNotifyWindow((OAHWND)NULL, 0, 0);
// Release and zero DirectShow interfaces_RELEASE(pME);_RELEASE(pMS);_RELEASE(pMP);_RELEASE(pMC);_RELEASE(pBA);_RELEASE(pBV);_RELEASE(pVW);_RELEASE(pGB);
}
//ЯMsg(TCHAR *szFormat, ...)
{szBuffer[1024]; // Large buffer for long filenames or URLssize_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);int LASTCHAR = NUMCHARS - 1;
// Format the input string_list pArgs;_start(pArgs, szFormat);
// Use a bounded buffer size to prevent buffer overruns. Limit count to
// character size minus one to allow for a NULL terminating character.
_vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);_end(pArgs);
// Ensure that the formatted string is NULL-terminated[LASTCHAR] = TEXT('\0');
// Display a message box with the formatted string(NULL, szBuffer, TEXT("PlayWnd Sample"), MB_OK);
}
//ЯToggleMute(void)
{hr=S_OK;((!pGB) || (!pBA))S_OK;
// Read current volume= pBA->get_Volume(&g_lVolume);(hr == E_NOTIMPL)
{
// Fail quietly if this is a video-only media fileS_OK;
}if (FAILED(hr))
{(TEXT("Failed to read audio volume! hr=0x%x\r\n"), hr);hr;
}
// Switch volume levels(g_lVolume == VOLUME_FULL)_lVolume = VOLUME_SILENCE;_lVolume = VOLUME_FULL;
// Set new volume(pBA->put_Volume(g_lVolume));
//UpdateMainTitle();hr;
}ToggleFullScreen(void)
{hr=S_OK;lMode;HWND hDrain=0;
// Don't bother with full-screen for audio-only files((g_bAudioOnly) || (!pVW))S_OK;
// Read current state(pVW->get_FullScreenMode(&lMode));(lMode == OAFALSE)
{
// Save current message drain(pVW->get_MessageDrain((OAHWND *) &hDrain));
// Set message drain to application main window(pVW->put_MessageDrain((OAHWND) ghApp));
// Switch to full-screen mode= OATRUE;(pVW->put_FullScreenMode(lMode));_bFullscreen = TRUE;
}
{
// Switch back to windowed mode= OAFALSE;(pVW->put_FullScreenMode(lMode));
// Undo change of message drain(pVW->put_MessageDrain((OAHWND) hDrain));
// Reset video window(pVW->SetWindowForeground(-1));
// Reclaim keyboard focus for player application(ghApp);(ghApp);(ghApp);_bFullscreen = FALSE;
}hr;
}
//ЯHandleGraphEvent(void)
{evCode, evParam1, evParam2;hr=S_OK;
// Make sure that we don't access the media event interface
// after it has already been released.(!pME)S_OK;
// Process all queued events(SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
(LONG_PTR *) &evParam2, 0)))
{
// Free memory associated with callback, since we're not using it= pME->FreeEventParams(evCode, evParam1, evParam2);
// If this is the end of the clip, reset to beginning(EC_COMPLETE == evCode)
{pos=0;
// Reset to first frame of movie= pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,, AM_SEEKING_NoPositioning);(FAILED(hr))
{
// Some custom filters (like the Windows CE MIDI filter)
// may not implement seeking interfaces (IMediaSeeking)
// to allow seeking to the start. In that case, just stop
// and restart for the same effect. This should not be
// necessary in most cases.(FAILED(hr = pMC->Stop()))
{(TEXT("Failed(0x%08lx) to stop media clip!\r\n"), hr);;
}
(FAILED(hr = pMC->Run()))
{(TEXT("Failed(0x%08lx) to reset media clip!\r\n"), hr);;
}
}
}
hr;
}
}