開発環境 |
Microsoft Visual Studio Express 2013 for Windows Desktop |
実行環境 |
Microsoft Windows 8.1 (64bit) |
プロジェクトの種類 |
Visual C++/Win32 プロジェクト |
プロジェクト名 |
BasicPlayback |
アプリケーションの種類 |
Windows アプリケーション |
追加のオプション |
空のプロジェクト、SDLチェック |
作りかけ。
参考
player.cpp
#pragma comment(lib, "mf")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")
#pragma comment(lib, "strmiids")
#include "player.h"
#pragma comment(lib, "shlwapi")
template <class Q>
HRESULT GetEventObject(IMFMediaEvent *pEvent, Q **ppObject)
{
*ppObject = NULL;
PROPVARIANT var;
HRESULT hr = pEvent->GetValue(&var);
if (SUCCEEDED(hr))
{
if (var.vt == VT_UNKNOWN)
{
hr = var.punkVal->QueryInterface(ppObject);
}
else
{
hr = MF_E_INVALIDTYPE;
}
PropVariantClear(&var);
}
return hr;
}
HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource);
HRESULT CreatePlaybackTopology(
IMFMediaSource *pSource,
IMFPresentationDescriptor *pPD,
HWND hVideoWnd,
IMFTopology **ppTopology);
HRESULT CPlayer::CreateInstance(
HWND hVideo,
HWND hEvent,
CPlayer **ppPlayer)
{
if (ppPlayer == NULL)
{
return E_POINTER;
}
CPlayer *pPlayer = new (std::nothrow) CPlayer(hVideo, hEvent);
if (pPlayer == NULL)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pPlayer->Initialize();
if (SUCCEEDED(hr))
{
*ppPlayer = pPlayer;
}
else
{
pPlayer->Release();
}
return hr;
}
HRESULT CPlayer::Initialize()
{
HRESULT hr = MFStartup(MF_VERSION);
if (SUCCEEDED(hr))
{
m_hCloseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hCloseEvent == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
CPlayer::CPlayer(HWND hVideo, HWND hEvent) :
m_pSession(NULL),
m_pSource(NULL),
m_pVideoDisplay(NULL),
m_hwndVideo(hVideo),
m_hwndEvent(hEvent),
m_state(Closed),
m_hCloseEvent(NULL),
m_nRefCount(1)
{
}
CPlayer::~CPlayer()
{
assert(m_pSession == NULL);
Shutdown();
}
HRESULT CPlayer::QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(CPlayer, IMFAsyncCallback),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
ULONG CPlayer::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
ULONG CPlayer::Release()
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
return uCount;
}
HRESULT CPlayer::OpenURL(const WCHAR *sURL)
{
IMFTopology *pTopology = NULL;
IMFPresentationDescriptor *pSourcePD = NULL;
HRESULT hr = CreateSession();
if (FAILED(hr)) goto done;
hr = CreateMediaSource(sURL, &m_pSource);
if (FAILED(hr)) goto done;
hr = m_pSource->CreatePresentationDescriptor(&pSourcePD);
if (FAILED(hr)) goto done;
hr = CreatePlaybackTopology(m_pSource, pSourcePD, m_hwndVideo, &pTopology);
if (FAILED(hr)) goto done;
hr = m_pSession->SetTopology(0, pTopology);
if (FAILED(hr)) goto done;
m_state = OpenPending;
done:
if (FAILED(hr))
{
m_state = Closed;
}
SafeRelease(&pSourcePD);
SafeRelease(&pTopology);
return hr;
}
HRESULT CPlayer::Pause()
{
if (m_state != Started)
{
return MF_E_INVALIDREQUEST;
}
if (m_pSession == NULL || m_pSource == NULL)
{
return E_UNEXPECTED;
}
HRESULT hr = m_pSession->Pause();
if (SUCCEEDED(hr))
{
m_state = Paused;
}
return hr;
}
HRESULT CPlayer::Stop()
{
if (m_state != Started && m_state != Paused)
{
return MF_E_INVALIDREQUEST;
}
if (m_pSession == NULL)
{
return E_UNEXPECTED;
}
HRESULT hr = m_pSession->Stop();
if (SUCCEEDED(hr))
{
m_state = Stopped;
}
return hr;
}
HRESULT CPlayer::Repaint()
{
if (m_pVideoDisplay)
{
return m_pVideoDisplay->RepaintVideo();
}
else
{
return S_OK;
}
}
HRESULT CPlayer::ResizeVideo(WORD width, WORD height)
{
if (m_pVideoDisplay)
{
RECT rcDest = { 0, 0, width, height };
return m_pVideoDisplay->SetVideoPosition(NULL, &rcDest);
}
else
{
return S_OK;
}
}
HRESULT CPlayer::Invoke(IMFAsyncResult *pResult)
{
MediaEventType meType = MEUnknown;
IMFMediaEvent *pEvent = NULL;
HRESULT hr = m_pSession->EndGetEvent(pResult, &pEvent);
if (FAILED(hr)) goto done;
hr = pEvent->GetType(&meType);
if (FAILED(hr)) goto done;
if (meType == MESessionClosed)
{
SetEvent(m_hCloseEvent);
}
else
{
hr = m_pSession->BeginGetEvent(this, NULL);
if (FAILED(hr)) goto done;
}
if (m_state != Closing)
{
pEvent->AddRef();
PostMessage(m_hwndEvent, WM_APP_PLAYER_EVENT,
(WPARAM)pEvent, (LPARAM)meType);
}
done:
SafeRelease(&pEvent);
return S_OK;
}
HRESULT CPlayer::HandleEvent(UINT_PTR pEventPtr)
{
HRESULT hrStatus = S_OK;
MediaEventType meType = MEUnknown;
IMFMediaEvent *pEvent = (IMFMediaEvent*)pEventPtr;
if (pEvent == NULL)
{
return E_POINTER;
}
HRESULT hr = pEvent->GetType(&meType);
if (FAILED(hr)) goto done;
hr = pEvent->GetStatus(&hrStatus);
if (SUCCEEDED(hr) && FAILED(hrStatus))
{
hr = hrStatus;
}
if (FAILED(hr)) goto done;
switch (meType)
{
case MESessionTopologyStatus:
hr = OnTopologyStatus(pEvent);
break;
case MEEndOfPresentation:
hr = OnPresentationEnded(pEvent);
break;
case MENewPresentation:
hr = OnNewPresentation(pEvent);
break;
default:
hr = OnSessionEvent(pEvent, meType);
break;
}
done:
SafeRelease(&pEvent);
return hr;
}
HRESULT CPlayer::Shutdown()
{
HRESULT hr = CloseSession();
MFShutdown();
if (m_hCloseEvent)
{
CloseHandle(m_hCloseEvent);
m_hCloseEvent = NULL;
}
return hr;
}
HRESULT CPlayer::OnTopologyStatus(IMFMediaEvent *pEvent)
{
UINT32 status;
HRESULT hr = pEvent->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, &status);
if (SUCCEEDED(hr) && (status == MF_TOPOSTATUS_READY))
{
SafeRelease(&m_pVideoDisplay);
(void)MFGetService(m_pSession, MR_VIDEO_RENDER_SERVICE,
IID_PPV_ARGS(&m_pVideoDisplay));
hr = StartPlayback();
}
return hr;
}
HRESULT CPlayer::OnPresentationEnded(IMFMediaEvent *pEvent)
{
m_state = Stopped;
return S_OK;
}
HRESULT CPlayer::OnNewPresentation(IMFMediaEvent *pEvent)
{
IMFPresentationDescriptor *pPD = NULL;
IMFTopology *pTopology = NULL;
HRESULT hr = GetEventObject(pEvent, &pPD);
if (FAILED(hr)) goto done;
hr = CreatePlaybackTopology(m_pSource, pPD, m_hwndVideo, &pTopology);
if (FAILED(hr)) goto done;
hr = m_pSession->SetTopology(0, pTopology);
if (FAILED(hr)) goto done;
m_state = OpenPending;
done:
SafeRelease(&pTopology);
SafeRelease(&pPD);
return S_OK;
}
HRESULT CPlayer::CreateSession()
{
HRESULT hr = CloseSession();
if (FAILED(hr)) goto done;
assert(m_state == Closed);
hr = MFCreateMediaSession(NULL, &m_pSession);
if (FAILED(hr)) goto done;
hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);
if (FAILED(hr)) goto done;
m_state = Ready;
done:
return hr;
}
HRESULT CPlayer::CloseSession()
{
HRESULT hr = S_OK;
SafeRelease(&m_pVideoDisplay);
if (m_pSession)
{
DWORD dwWaitResult = 0;
m_state = Closing;
hr = m_pSession->Close();
if (SUCCEEDED(hr))
{
dwWaitResult = WaitForSingleObject(m_hCloseEvent, 5000);
if (dwWaitResult == WAIT_TIMEOUT)
{
assert(FALSE);
}
}
}
if (SUCCEEDED(hr))
{
if (m_pSource)
{
(void)m_pSource->Shutdown();
}
if (m_pSession)
{
(void)m_pSession->Shutdown();
}
}
SafeRelease(&m_pSource);
SafeRelease(&m_pSession);
m_state = Closed;
return hr;
}
HRESULT CPlayer::StartPlayback()
{
assert(m_pSession != NULL);
PROPVARIANT varStart;
PropVariantInit(&varStart);
HRESULT hr = m_pSession->Start(&GUID_NULL, &varStart);
if (SUCCEEDED(hr))
{
m_state = Started;
}
PropVariantClear(&varStart);
return hr;
}
HRESULT CPlayer::Play()
{
if (m_state != Paused && m_state != Stopped)
{
return MF_E_INVALIDREQUEST;
}
if (m_pSession == NULL || m_pSource == NULL)
{
return E_UNEXPECTED;
}
return StartPlayback();
}
HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource)
{
MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
IMFSourceResolver *pSourceResolver = NULL;
IUnknown *pSource = NULL;
HRESULT hr = MFCreateSourceResolver(&pSourceResolver);
if (FAILED(hr)) goto done;
hr = pSourceResolver->CreateObjectFromURL(
sURL,
MF_RESOLUTION_MEDIASOURCE,
NULL,
&ObjectType,
&pSource
);
if (FAILED(hr)) goto done;
hr = pSource->QueryInterface(IID_PPV_ARGS(ppSource));
done:
SafeRelease(&pSourceResolver);
SafeRelease(&pSource);
return hr;
}
HRESULT CreateMediaSinkActivate(
IMFStreamDescriptor *pSourceSD,
HWND hVideoWindow,
IMFActivate **ppActivate)
{
IMFMediaTypeHandler *pHandler = NULL;
IMFActivate *pActivate = NULL;
HRESULT hr = pSourceSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr)) goto done;
GUID guidMajorType;
hr = pHandler->GetMajorType(&guidMajorType);
if (FAILED(hr)) goto done;
if (MFMediaType_Audio == guidMajorType)
{
hr = MFCreateAudioRendererActivate(&pActivate);
}
else if (MFMediaType_Video == guidMajorType)
{
hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate);
}
else
{
hr = E_FAIL;
}
if (FAILED(hr)) goto done;
*ppActivate = pActivate;
(*ppActivate)->AddRef();
done:
SafeRelease(&pHandler);
SafeRelease(&pActivate);
return hr;
}
HRESULT AddSourceNode(
IMFTopology *pTopology,
IMFMediaSource *pSource,
IMFPresentationDescriptor *pPD,
IMFStreamDescriptor *pSD,
IMFTopologyNode **ppNode)
{
IMFTopologyNode *pNode = NULL;
HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode);
if (FAILED(hr)) goto done;
hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);
if (FAILED(hr)) goto done;
hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD);
if (FAILED(hr)) goto done;
hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD);
if (FAILED(hr)) goto done;
hr = pTopology->AddNode(pNode);
if (FAILED(hr)) goto done;
*ppNode = pNode;
(*ppNode)->AddRef();
done:
SafeRelease(&pNode);
return hr;
}
HRESULT AddOutputNode(
IMFTopology *pTopology,
IMFActivate *pActivate,
DWORD dwId,
IMFTopologyNode **ppNode)
{
IMFTopologyNode *pNode = NULL;
HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
if (FAILED(hr)) goto done;
hr = pNode->SetObject(pActivate);
if (FAILED(hr)) goto done;
hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId);
if (FAILED(hr)) goto done;
hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
if (FAILED(hr)) goto done;
hr = pTopology->AddNode(pNode);
if (FAILED(hr)) goto done;
*ppNode = pNode;
(*ppNode)->AddRef();
done:
SafeRelease(&pNode);
return hr;
}
HRESULT AddBranchToPartialTopology(
IMFTopology *pTopology,
IMFMediaSource *pSource,
IMFPresentationDescriptor *pPD,
DWORD iStream,
HWND hVideoWnd)
{
IMFStreamDescriptor *pSD = NULL;
IMFActivate *pSinkActivate = NULL;
IMFTopologyNode *pSourceNode = NULL;
IMFTopologyNode *pOutputNode = NULL;
BOOL fSelected = FALSE;
HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
if (FAILED(hr)) goto done;
if (fSelected)
{
hr = CreateMediaSinkActivate(pSD, hVideoWnd, &pSinkActivate);
if (FAILED(hr)) goto done;
hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode);
if (FAILED(hr)) goto done;
hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);
if (FAILED(hr)) goto done;
hr = pSourceNode->ConnectOutput(0, pOutputNode, 0);
}
done:
SafeRelease(&pSD);
SafeRelease(&pSinkActivate);
SafeRelease(&pSourceNode);
SafeRelease(&pOutputNode);
return hr;
}
HRESULT CreatePlaybackTopology(
IMFMediaSource *pSource,
IMFPresentationDescriptor *pPD,
HWND hVideoWnd,
IMFTopology **ppTopology)
{
IMFTopology *pTopology = NULL;
DWORD cSourceStreams = 0;
HRESULT hr = MFCreateTopology(&pTopology);
if (FAILED(hr)) goto done;
hr = pPD->GetStreamDescriptorCount(&cSourceStreams);
if (FAILED(hr)) goto done;
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, hVideoWnd);
if (FAILED(hr)) goto done;
}
*ppTopology = pTopology;
(*ppTopology)->AddRef();
done:
SafeRelease(&pTopology);
return hr;
}
player.h
#include <new>
#include <Windows.h>
#include <ShObjIdl.h>
#include <Shlwapi.h>
#include <assert.h>
#include <strsafe.h>
#include <mfapi.h>
#include <mfidl.h>
#include <Mferror.h>
#include <evr.h>
#include "resource.h"
template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
const UINT WM_APP_PLAYER_EVENT = WM_APP + 1;
enum PlayerState
{
Closed = 0,
Ready,
OpenPending,
Started,
Paused,
Stopped,
Closing
};
class CPlayer : public IMFAsyncCallback
{
public:
static HRESULT CreateInstance(HWND hVideo, HWND hEvent, CPlayer **ppPlayer);
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP GetParameters(DWORD*, DWORD*)
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
HRESULT OpenURL(const WCHAR *sURL);
HRESULT Play();
HRESULT Pause();
HRESULT Stop();
HRESULT Shutdown();
HRESULT HandleEvent(UINT_PTR pUnkPtr);
PlayerState GetState() const { return m_state; }
HRESULT Repaint();
HRESULT ResizeVideo(WORD width, WORD height);
BOOL HasVideo() const { return (m_pVideoDisplay != NULL); }
protected:
CPlayer(HWND hVideo, HWND hEvent);
virtual ~CPlayer();
HRESULT Initialize();
HRESULT CreateSession();
HRESULT CloseSession();
HRESULT StartPlayback();
virtual HRESULT OnTopologyStatus(IMFMediaEvent *pEvent);
virtual HRESULT OnPresentationEnded(IMFMediaEvent *pEvent);
virtual HRESULT OnNewPresentation(IMFMediaEvent *pEvent);
virtual HRESULT OnSessionEvent(IMFMediaEvent*, MediaEventType)
{
return S_OK;
}
protected:
long m_nRefCount;
IMFMediaSession *m_pSession;
IMFMediaSource *m_pSource;
IMFVideoDisplayControl *m_pVideoDisplay;
HWND m_hwndVideo;
HWND m_hwndEvent;
PlayerState m_state;
HANDLE m_hCloseEvent;
};
player.rc
#include "resource.h"
#include <windows.h>
IDC_MFPLAYBACK MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open File", ID_FILE_OPENFILE
MENUITEM "Open &Url", ID_FILE_OPENURL
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
END
IDD_OPENURL DIALOGEX 0, 0, 186, 90
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Open URL"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,75,69,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,69,50,14
EDITTEXT IDC_EDIT_URL,7,21,172,14,ES_AUTOHSCROLL
LTEXT "Enter the URL to open:",IDC_STATIC,7,7,104,8
END
resource.h
#define IDD_MFPLAYBACK_DIALOG 102
#define IDM_EXIT 105
#define IDC_MFPLAYBACK 109
#define IDD_OPENURL 129
#define IDC_EDIT_URL 1000
#define ID_FILE_OPENFILE 32771
#define ID_FILE_OPENURL 32772
#define IDC_STATIC -1
winmaincpp
#include "player.h"
PCWSTR szTitle = L"BasicPlayback";
PCWSTR szWindowClass = L"MFBASICPLAYBACK";
HINSTANCE g_hInstance;
BOOL g_bRepaintClient = TRUE;
CPlayer *g_pPlayer = NULL;
BOOL InitInstance(HINSTANCE hInst, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK OpenUrlDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void NotifyError(HWND hwnd, PCWSTR pszErrorMessage, HRESULT hrErr);
void UpdateUI(HWND hwnd, PlayerState state);
HRESULT AllocGetWindowText(HWND hwnd, WCHAR **pszText, DWORD *pcchLen);
LRESULT OnCreateWindow(HWND hwnd);
void OnFileOpen(HWND hwnd);
void OnOpenURL(HWND hwnd);
void OnPlayerEvent(HWND hwnd, WPARAM pUnkPtr);
void OnPaint(HWND hwnd);
void OnResize(WORD width, WORD height);
void OnKeyPress(WPARAM key);
struct OpenUrlDialogInfo
{
WCHAR *pszURL;
DWORD cch;
};
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
MSG msg;
if (!InitInstance(hInstance, nCmdShow))
{
NotifyError(NULL, L"Could not initialize the application.",
HRESULT_FROM_WIN32(GetLastError()));
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (g_pPlayer)
{
g_pPlayer->Shutdown();
SafeRelease(&g_pPlayer);
}
return 0;
}
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
HWND hwnd;
WNDCLASSEX wcex = { sizeof WNDCLASSEX };
g_hInstance = hInst;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInst;
wcex.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MFPLAYBACK);
wcex.lpszClassName = szWindowClass;
if (RegisterClassEx(&wcex) == 0)
{
return FALSE;
}
hwnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);
if (hwnd == 0)
{
return FALSE;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return OnCreateWindow(hwnd);
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_EXIT:
DestroyWindow(hwnd);
break;
case ID_FILE_OPENFILE:
OnFileOpen(hwnd);
break;
case ID_FILE_OPENURL:
OnOpenURL(hwnd);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
break;
case WM_PAINT:
OnPaint(hwnd);
break;
case WM_SIZE:
OnResize(LOWORD(lParam), HIWORD(lParam));
break;
case WM_ERASEBKGND:
return 1;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CHAR:
OnKeyPress(wParam);
break;
case WM_APP_PLAYER_EVENT:
OnPlayerEvent(hwnd, wParam);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
void OnFileOpen(HWND hwnd)
{
IFileOpenDialog *pFileOpen = NULL;
IShellItem *pItem = NULL;
PWSTR pszFilePath = NULL;
HRESULT hr = CoCreateInstance(__uuidof(FileOpenDialog), NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpen));
if (FAILED(hr)) goto done;
hr = pFileOpen->Show(NULL);
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
hr = S_OK;
goto done;
}
else if (FAILED(hr))
{
goto done;
}
hr = pFileOpen->GetResult(&pItem);
if (FAILED(hr)) goto done;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
if (FAILED(hr)) goto done;
hr = g_pPlayer->OpenURL(pszFilePath);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, OpenPending);
}
done:
if (FAILED(hr))
{
NotifyError(hwnd, L"Could not open the file.", hr);
UpdateUI(hwnd, Closed);
}
CoTaskMemFree(pszFilePath);
SafeRelease(&pItem);
SafeRelease(&pFileOpen);
}
void OnOpenURL(HWND hwnd)
{
HRESULT hr = S_OK;
OpenUrlDialogInfo url = { 0 };
if (IDOK == DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_OPENURL), hwnd,
OpenUrlDialogProc, (LPARAM)&url))
{
hr = g_pPlayer->OpenURL(url.pszURL);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, OpenPending);
}
else
{
NotifyError(hwnd, L"Could not open this URL.", hr);
UpdateUI(hwnd, Closed);
}
}
CoTaskMemFree(url.pszURL);
}
LRESULT OnCreateWindow(HWND hwnd)
{
HRESULT hr = CPlayer::CreateInstance(hwnd, hwnd, &g_pPlayer);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, Closed);
return 0;
}
else
{
NotifyError(NULL, L"Could not initialize the player object.", hr);
return -1;
}
}
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (g_pPlayer && g_pPlayer->HasVideo())
{
g_pPlayer->Repaint();
}
else
{
RECT rc;
GetClientRect(hwnd, &rc);
FillRect(hdc, &rc, (HBRUSH)COLOR_WINDOW);
}
EndPaint(hwnd, &ps);
}
void OnResize(WORD width, WORD height)
{
if (g_pPlayer)
{
g_pPlayer->ResizeVideo(width, height);
}
}
void OnKeyPress(WPARAM key)
{
switch (key)
{
case VK_SPACE:
if (g_pPlayer->GetState() == Started)
{
g_pPlayer->Pause();
}
else if (g_pPlayer->GetState() == Paused)
{
g_pPlayer->Play();
}
break;
}
}
void OnPlayerEvent(HWND hwnd, WPARAM pUnkPtr)
{
HRESULT hr = g_pPlayer->HandleEvent(pUnkPtr);
if (FAILED(hr))
{
NotifyError(hwnd, L"An error occurred.", hr);
}
UpdateUI(hwnd, g_pPlayer->GetState());
}
void UpdateUI(HWND hwnd, PlayerState state)
{
BOOL bWaiting = FALSE;
BOOL bPlayback = FALSE;
assert(g_pPlayer != NULL);
switch (state)
{
case OpenPending:
bWaiting = TRUE;
break;
case Started:
bPlayback = TRUE;
break;
case Paused:
bPlayback = TRUE;
break;
}
HMENU hMenu = GetMenu(hwnd);
UINT uEnable = MF_BYCOMMAND | (bWaiting ? MF_GRAYED : MF_ENABLED);
EnableMenuItem(hMenu, ID_FILE_OPENFILE, uEnable);
EnableMenuItem(hMenu, ID_FILE_OPENURL, uEnable);
if (bPlayback && g_pPlayer->HasVideo())
{
g_bRepaintClient = FALSE;
}
else
{
g_bRepaintClient = TRUE;
}
}
void NotifyError(HWND hwnd, PCWSTR pszErrorMessage, HRESULT hrErr)
{
const size_t MESSAGE_LEN = 512;
WCHAR message[MESSAGE_LEN];
if (SUCCEEDED(StringCchPrintf(message, MESSAGE_LEN, L"%s (HRESULT = 0x%X)",
pszErrorMessage, hrErr)))
{
MessageBox(hwnd, message, NULL, MB_OK | MB_ICONERROR);
}
}
INT_PTR CALLBACK OpenUrlDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static OpenUrlDialogInfo *pUrl = NULL;
BOOL result = FALSE;
switch (message)
{
case WM_INITDIALOG:
pUrl = (OpenUrlDialogInfo*)lParam;
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (pUrl)
{
if (SUCCEEDED(AllocGetWindowText(GetDlgItem(hDlg, IDC_EDIT_URL),
&pUrl->pszURL, &pUrl->cch)))
{
result = TRUE;
}
}
EndDialog(hDlg, result ? IDOK : IDABORT);
break;
case IDCANCEL:
EndDialog(hDlg, LOWORD(IDCANCEL));
break;
}
return (INT_PTR)FALSE;
}
return (INT_PTR)FALSE;
}
HRESULT AllocGetWindowText(HWND hwnd, WCHAR **pszText, DWORD *pcchLen)
{
if (pszText == NULL || pcchLen == NULL)
{
return E_POINTER;
}
*pszText = NULL;
int cch = GetWindowTextLength(hwnd);
if (cch < 0)
{
return E_UNEXPECTED;
}
PWSTR pszTmp = (PWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (cch + 1));
if (!pszTmp)
{
return E_OUTOFMEMORY;
}
if (cch == 0)
{
pszTmp[0] = L'\0';
}
else
{
int res = GetWindowText(hwnd, pszTmp, (cch + 1));
if (res == 0)
{
CoTaskMemFree(pszTmp);
return __HRESULT_FROM_WIN32(GetLastError());
}
}
*pszText = pszTmp;
*pcchLen = static_cast<DWORD>(cch);
return S_OK;
}
最終更新:2014年07月16日 14:22