PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Core/Dependencies/Media SDK 2012/samples/sample_dshow_player/src/mainwindow.cpp

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
C++ | 904 lines | 552 code | 197 blank | 155 comment | 71 complexity | 7fcd8353ce5980d86e3eb8731dca1435 MD5 | raw file
  1. /* /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // INTEL CORPORATION PROPRIETARY INFORMATION
  4. // This software is supplied under the terms of a license agreement or
  5. // nondisclosure agreement with Intel Corporation and may not be copied
  6. // or disclosed except in accordance with the terms of that agreement.
  7. // Copyright(c) 2008-2011 Intel Corporation. All Rights Reserved.
  8. //
  9. //
  10. */
  11. //////////////////////////////////////////////////////////////////////////
  12. // MainWindow.cpp: Main application window.
  13. //
  14. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  15. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  16. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  17. // PARTICULAR PURPOSE.
  18. //
  19. // Copyright (c) Microsoft Corporation. All rights reserved.
  20. //
  21. //////////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "MainWindow.h"
  24. const LONG ONE_MSEC = 10000; // The number of 100-ns in 1 msec
  25. const UINT_PTR IDT_TIMER1 = 1; // Timer ID
  26. const UINT TICK_FREQ = 200; // Timer frequency in msec
  27. // Forward declarations of functions included in this code module:
  28. void NotifyError(HWND hwnd, TCHAR* sMessage, HRESULT hrStatus);
  29. //-----------------------------------------------------------------------------
  30. // MainWindow constructor.
  31. //-----------------------------------------------------------------------------
  32. MainWindow::MainWindow() : brush(NULL), m_timerID(0), m_pPlayer(NULL)
  33. {
  34. }
  35. //-----------------------------------------------------------------------------
  36. // MainWindow destructor.
  37. //-----------------------------------------------------------------------------
  38. MainWindow::~MainWindow()
  39. {
  40. if (brush)
  41. {
  42. DeleteObject(brush);
  43. }
  44. StopTimer();
  45. MSDK_SAFE_DELETE(m_pPlayer);
  46. }
  47. INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  48. {
  49. switch (uMsg)
  50. {
  51. case WM_COMMAND:
  52. EndDialog(hwndDlg, 0);
  53. break;
  54. }
  55. return 0;
  56. };
  57. //-----------------------------------------------------------------------------
  58. // MainWindow::OnReceiveMessage
  59. // Description: Handles window messages
  60. //-----------------------------------------------------------------------------
  61. LRESULT MainWindow::OnReceiveMessage(UINT message, WPARAM wParam, LPARAM lParam)
  62. {
  63. int wmId, wmEvent;
  64. HRESULT hr;
  65. switch (message)
  66. {
  67. case WM_CREATE:
  68. hr = OnCreate();
  69. if (FAILED(hr))
  70. {
  71. // Fail and quit.
  72. NotifyError(m_hwnd, TEXT("Cannot initialize the application."), hr);
  73. return -1;
  74. }
  75. break;
  76. case WM_SIZE:
  77. OnSize();
  78. break;
  79. case WM_PAINT:
  80. OnPaint();
  81. break;
  82. case WM_MOVE:
  83. OnPaint();
  84. break;
  85. case WM_ERASEBKGND:
  86. return 1;
  87. case WM_DESTROY:
  88. PostQuitMessage(0);
  89. break;
  90. case WM_TIMER:
  91. OnTimer();
  92. break;
  93. case WM_NOTIFY:
  94. OnWmNotify((NMHDR*)lParam);
  95. break;
  96. case WM_COMMAND:
  97. wmId = LOWORD(wParam);
  98. wmEvent = HIWORD(wParam);
  99. switch (wmId)
  100. {
  101. case IDM_EXIT:
  102. DestroyWindow(m_hwnd);
  103. break;
  104. case ID_FILE_OPENFILE:
  105. OnFileOpen(0);
  106. break;
  107. case ID_FILE_PLAYINS3D:
  108. OnFileOpen(1);
  109. break;
  110. case IDC_BUTTON_PLAY:
  111. OnPlay();
  112. break;
  113. case IDC_BUTTON_STOP:
  114. OnStop();
  115. break;
  116. case IDC_BUTTON_PAUSE:
  117. OnPause();
  118. break;
  119. case IDC_BUTTON_MUTE:
  120. OnMute();
  121. break;
  122. case ID_TRANSCODEFILE_MP4_H264_MP3:
  123. OnFileTranscode(1);
  124. break;
  125. case ID_TRANSCODEFILE_MP4_H264_AAC:
  126. OnFileTranscode(2);
  127. break;
  128. case ID_TRANSCODEFILE_MPEG_TS_MPEG2_MP3:
  129. OnFileTranscode(3);
  130. break;
  131. case ID_TRANSCODEFILE_MPEG_TS_H264_AAC:
  132. OnFileTranscode(4);
  133. break;
  134. case ID_CONFIGURE_ENCODER:
  135. ShowFilterProperties(m_pPlayer->GetEncoder());
  136. break;
  137. case ID_CONFIGURE_RENDER:
  138. ShowFilterProperties(m_pPlayer->GetRender());
  139. break;
  140. case ID_HELP_ABOUT:
  141. DialogBox(m_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), m_hwnd, DialogProc);
  142. break;
  143. }
  144. break;
  145. // Private filter graph message.
  146. case WM_GRAPH_EVENT:
  147. hr = m_pPlayer->HandleGraphEvent(this);
  148. break;
  149. default:
  150. return BaseWindow::OnReceiveMessage(message, wParam, lParam);
  151. }
  152. return 0;
  153. }
  154. //-----------------------------------------------------------------------------
  155. // MainWindow::OnCreate
  156. // Description: Called when the window is created.
  157. //-----------------------------------------------------------------------------
  158. HRESULT MainWindow::OnCreate()
  159. {
  160. HRESULT hr = S_OK;
  161. // Create the background brush.
  162. brush = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0x80, 0xFF));
  163. if (brush == NULL)
  164. {
  165. hr = __HRESULT_FROM_WIN32(GetLastError());
  166. }
  167. // Create the rebar control.
  168. if (SUCCEEDED(hr))
  169. {
  170. hr = rebar.Create(m_hInstance, m_hwnd, IDC_REBAR_CONTROL);
  171. }
  172. // Create the toolbar control.
  173. if (SUCCEEDED(hr))
  174. {
  175. hr = toolbar.Create(m_hInstance, m_hwnd, IDC_TOOLBAR, TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_TOP);
  176. }
  177. // Set the image list for toolbar buttons (normal state).
  178. if (SUCCEEDED(hr))
  179. {
  180. hr = toolbar.SetImageList(
  181. Toolbar::Normal, // Image list for normal state
  182. IDB_TOOLBAR_IMAGES_NORMAL, // Bitmap resource
  183. Size(48, 48), // Size of each button
  184. 5, // Number of buttons
  185. RGB(0xFF, 0x00, 0xFF) // Color mask
  186. );
  187. }
  188. // Set the image list for toolbar buttons (disabled state).
  189. if (SUCCEEDED(hr))
  190. {
  191. hr = toolbar.SetImageList(
  192. Toolbar::Disabled, // Image list for normal state
  193. IDB_TOOLBAR_IMAGES_DISABLED, // Bitmap resource
  194. Size(48, 48), // Size of each button
  195. 5, // Number of buttons
  196. RGB(0xFF, 0x00, 0xFF) // Color mask
  197. );
  198. }
  199. // Add buttons to the toolbar.
  200. if (SUCCEEDED(hr))
  201. {
  202. // Play
  203. hr = toolbar.AddButton(Toolbar::Button(ID_IMAGE_PLAY, IDC_BUTTON_PLAY));
  204. }
  205. if (SUCCEEDED(hr))
  206. {
  207. // Stop
  208. hr = toolbar.AddButton(Toolbar::Button(ID_IMAGE_STOP, IDC_BUTTON_STOP));
  209. }
  210. if (SUCCEEDED(hr))
  211. {
  212. // Pause
  213. hr = toolbar.AddButton(Toolbar::Button(ID_IMAGE_PAUSE, IDC_BUTTON_PAUSE));
  214. }
  215. if (SUCCEEDED(hr))
  216. {
  217. // Mute
  218. hr = toolbar.AddButton(Toolbar::Button(ID_IMAGE_MUTE_OFF, IDC_BUTTON_MUTE));
  219. }
  220. // Add the toolbar to the rebar control.
  221. if (SUCCEEDED(hr))
  222. {
  223. hr = rebar.AddBand(toolbar.Window(), 0);
  224. }
  225. //// Create the slider for seeking.
  226. if (SUCCEEDED(hr))
  227. {
  228. hr = Slider_Init(); // Initialize the Slider control.
  229. }
  230. if (SUCCEEDED(hr))
  231. {
  232. hr = seekbar.Create(m_hwnd, Rect(0, 0, 300, 16), IDC_SEEKBAR);
  233. }
  234. if (SUCCEEDED(hr))
  235. {
  236. hr = seekbar.SetThumbBitmap(IDB_SLIDER_THUMB);
  237. seekbar.SetBackground(CreateSolidBrush(RGB(239, 239, 231)));
  238. seekbar.Enable(FALSE);
  239. }
  240. if (SUCCEEDED(hr))
  241. {
  242. hr = rebar.AddBand(seekbar.Window(), 1);
  243. }
  244. //// Create the slider for changing the volume.
  245. if (SUCCEEDED(hr))
  246. {
  247. hr = volumeSlider.Create(m_hwnd, Rect(0, 0, 100, 32), IDC_VOLUME);
  248. }
  249. if (SUCCEEDED(hr))
  250. {
  251. hr = volumeSlider.SetThumbBitmap(IDB_SLIDER_VOLUME);
  252. volumeSlider.SetBackground(CreateSolidBrush(RGB(239, 239, 231)));
  253. volumeSlider.Enable(TRUE);
  254. // Set the range of the volume slider. In my experience, only the top half of the
  255. // range is audible.
  256. volumeSlider.SetRange(MIN_VOLUME / 2, MAX_VOLUME);
  257. volumeSlider.SetPosition(MAX_VOLUME);
  258. }
  259. if (SUCCEEDED(hr))
  260. {
  261. hr = rebar.AddBand(volumeSlider.Window(), 2);
  262. }
  263. // Create the tooltip
  264. if (SUCCEEDED(hr))
  265. {
  266. hr = toolTip.Create(m_hwnd);
  267. }
  268. if (SUCCEEDED(hr))
  269. {
  270. toolTip.AddTool(volumeSlider.Window(), L"Volume");
  271. toolTip.AddTool(seekbar.Window(), L"Seek");
  272. rebar.SendMessage(RB_SETTOOLTIPS, (WPARAM)toolTip.Window(), 0);
  273. }
  274. // Create the DirectShow player object.
  275. if (SUCCEEDED(hr))
  276. {
  277. RECT rcWindow;
  278. RECT rcControl;
  279. // Find the client area of the application.
  280. GetClientRect(m_hwnd, &rcWindow);
  281. // Subtract the area of the rebar control.
  282. GetClientRect(rebar.Window(), &rcControl);
  283. SubtractRect(&rcWindow, &rcWindow, &rcControl);
  284. video = CreateWindowEx(NULL, L"STATIC", NULL, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE ,
  285. rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top,
  286. m_hwnd, (HMENU)NULL, m_hInstance, NULL);
  287. if (video)
  288. {
  289. m_pPlayer = new DShowPlayer(video);
  290. }
  291. if (m_pPlayer == NULL)
  292. {
  293. hr = E_OUTOFMEMORY;
  294. }
  295. }
  296. // Set the event notification window.
  297. if (SUCCEEDED(hr))
  298. {
  299. hr = m_pPlayer->SetEventWindow(m_hwnd, WM_GRAPH_EVENT);
  300. }
  301. // Set default UI state.
  302. if (SUCCEEDED(hr))
  303. {
  304. UpdateUI();
  305. }
  306. return hr;
  307. }
  308. //-----------------------------------------------------------------------------
  309. // MainWindow::OnPaint
  310. // Description: Called when the window should be painted.
  311. //-----------------------------------------------------------------------------
  312. void MainWindow::OnPaint()
  313. {
  314. PAINTSTRUCT ps;
  315. HDC hdc;
  316. hdc = BeginPaint(m_hwnd, &ps);
  317. if (m_pPlayer->State() != STATE_CLOSED && m_pPlayer->HasVideo())
  318. {
  319. // The player has video, so ask the player to repaint.
  320. m_pPlayer->Repaint(hdc);
  321. }
  322. else
  323. {
  324. // The player does not have video. Fill in our client region, not
  325. // including the area for the toolbar.
  326. RECT rcClient;
  327. RECT rcToolbar;
  328. GetClientRect(m_hwnd, &rcClient);
  329. GetClientRect(rebar.Window(), &rcToolbar);
  330. HRGN hRgn1 = CreateRectRgnIndirect(&rcClient);
  331. HRGN hRgn2 = CreateRectRgnIndirect(&rcToolbar);
  332. CombineRgn(hRgn1, hRgn1, hRgn2, RGN_DIFF);
  333. FillRgn(hdc, hRgn1, brush);
  334. DeleteObject(hRgn1);
  335. DeleteObject(hRgn2);
  336. }
  337. EndPaint(m_hwnd, &ps);
  338. }
  339. //-----------------------------------------------------------------------------
  340. // MainWindow::OnSize
  341. // Description: Called when the window is resized.
  342. //-----------------------------------------------------------------------------
  343. void MainWindow::OnSize()
  344. {
  345. // resize the toolbar
  346. SendMessage(toolbar.Window(), WM_SIZE, 0, 0);
  347. // resize the rebar
  348. SendMessage(rebar.Window(), WM_SIZE, 0, 0);
  349. RECT rcWindow;
  350. RECT rcControl;
  351. // Find the client area of the application.
  352. GetClientRect(m_hwnd, &rcWindow);
  353. // Subtract the area of the rebar control.
  354. GetClientRect(rebar.Window(), &rcControl);
  355. SubtractRect(&rcWindow, &rcWindow, &rcControl);
  356. // resize video window
  357. SetWindowPos(video, NULL, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, NULL);
  358. // What's left is the area for the video. Notify the player.
  359. m_pPlayer->UpdateVideoWindow(&rcWindow);
  360. }
  361. //-----------------------------------------------------------------------------
  362. // MainWindow::OnTimer
  363. // Description: Called when the timer elapses.
  364. //-----------------------------------------------------------------------------
  365. void MainWindow::OnTimer()
  366. {
  367. // If the player can seek, update the seek bar with the current position.
  368. if (m_pPlayer->CanSeek())
  369. {
  370. REFERENCE_TIME timeNow;
  371. if (SUCCEEDED(m_pPlayer->GetCurrentPosition(&timeNow)))
  372. {
  373. seekbar.SetPosition((LONG)(timeNow / ONE_MSEC));
  374. }
  375. }
  376. }
  377. //-----------------------------------------------------------------------------
  378. // MainWindow::OnWmNotify
  379. // Description: Handle WM_NOTIFY messages.
  380. //-----------------------------------------------------------------------------
  381. void MainWindow::OnWmNotify(const NMHDR *pHdr)
  382. {
  383. switch (pHdr->code)
  384. {
  385. case TTN_GETDISPINFO:
  386. // Display tool tips
  387. toolbar.ShowToolTip((NMTTDISPINFO*)pHdr);
  388. break;
  389. default:
  390. switch (pHdr->idFrom)
  391. {
  392. case IDC_SEEKBAR:
  393. OnSeekbarNotify((NMSLIDER_INFO*)pHdr);
  394. break;
  395. case IDC_VOLUME:
  396. OnVolumeSliderNotify((NMSLIDER_INFO*)pHdr);
  397. break;
  398. }
  399. break;
  400. }
  401. }
  402. //-----------------------------------------------------------------------------
  403. // MainWindow::OnSeekbarNotify
  404. // Description: Handle WM_NOTIFY messages from the seekbar.
  405. //-----------------------------------------------------------------------------
  406. void MainWindow::OnSeekbarNotify(const NMSLIDER_INFO *pInfo)
  407. {
  408. static PlaybackState state = STATE_CLOSED;
  409. // Pause when the scroll action begins.
  410. if (pInfo->hdr.code == SLIDER_NOTIFY_SELECT)
  411. {
  412. state = m_pPlayer->State();
  413. m_pPlayer->Pause();
  414. }
  415. // Update the position continuously.
  416. m_pPlayer->SetPosition((REFERENCE_TIME)ONE_MSEC * (REFERENCE_TIME)pInfo->position);
  417. // Restore the state at the end.
  418. if (pInfo->hdr.code == SLIDER_NOTIFY_RELEASE)
  419. {
  420. if (state == STATE_STOPPED)
  421. {
  422. m_pPlayer->Stop();
  423. }
  424. else if (state == STATE_RUNNING)
  425. {
  426. m_pPlayer->Play();
  427. }
  428. }
  429. }
  430. //-----------------------------------------------------------------------------
  431. // MainWindow::OnVolumeSliderNotify
  432. // Description: Handle WM_NOTIFY messages from the volume slider.
  433. //-----------------------------------------------------------------------------
  434. void MainWindow::OnVolumeSliderNotify(const NMSLIDER_INFO *pInfo)
  435. {
  436. m_pPlayer->SetVolume(pInfo->position);
  437. }
  438. void MainWindow::ShowFilterProperties(IBaseFilter * pFilter)
  439. {
  440. CComQIPtr<ISpecifyPropertyPages> pProp(pFilter);
  441. if (NULL == pProp.p)
  442. return;
  443. // Get the filter's name and IUnknown pointer.
  444. FILTER_INFO FilterInfo;
  445. if (SUCCEEDED(pFilter->QueryFilterInfo(&FilterInfo)))
  446. {
  447. CComPtr<IUnknown> pFilterUnk;
  448. pFilter->QueryInterface(IID_IUnknown, (void**)&pFilterUnk);
  449. if (NULL != pFilterUnk.p)
  450. {
  451. // Show the page.
  452. CAUUID caGUID;
  453. if (SUCCEEDED(pProp->GetPages(&caGUID)))
  454. {
  455. OleCreatePropertyFrame(
  456. m_hwnd, // Parent window
  457. 0, 0, // Reserved
  458. FilterInfo.achName, // Caption for the dialog box
  459. 1, // Number of objects (just the filter)
  460. &pFilterUnk.p, // Array of object pointers.
  461. caGUID.cElems, // Number of property pages
  462. caGUID.pElems, // Array of property page CLSIDs
  463. 0, // Locale identifier
  464. 0, NULL // Reserved
  465. );
  466. CoTaskMemFree(caGUID.pElems);
  467. }
  468. }
  469. FilterInfo.pGraph->Release();
  470. }
  471. }
  472. void MainWindow::OnFileTranscode(INT nType)
  473. {
  474. OPENFILENAME ofn;
  475. ZeroMemory(&ofn, sizeof(ofn));
  476. WCHAR szInputFileName[MAX_PATH];
  477. szInputFileName[0] = L'\0';
  478. WCHAR szOutputFileName[MAX_PATH];
  479. szOutputFileName[0] = L'\0';
  480. ofn.lStructSize = sizeof(ofn);
  481. ofn.hwndOwner = m_hwnd;
  482. ofn.hInstance = m_hInstance;
  483. ofn.lpstrFilter = L"All Files\0*.*\0\0";
  484. ofn.lpstrFile = szInputFileName;
  485. ofn.nMaxFile = MAX_PATH;
  486. ofn.Flags = OFN_FILEMUSTEXIST;
  487. HRESULT hr;
  488. BOOL bOpen = FALSE;
  489. bOpen = GetOpenFileName(&ofn);
  490. if (FALSE == bOpen)
  491. {
  492. return;
  493. }
  494. ofn.lpstrFile = szOutputFileName;
  495. ofn.Flags = 0;
  496. bOpen = GetSaveFileName(&ofn);
  497. if (FALSE == bOpen)
  498. {
  499. return;
  500. }
  501. hr = m_pPlayer->TranscodeFile(szInputFileName, szOutputFileName, nType);
  502. // Update the state of the UI.
  503. UpdateUI();
  504. // Invalidate the application window, in case there is an old video
  505. // frame from the previous file and there is no video now. (eg, the
  506. // new file is audio only, or we failed to open this file.)
  507. InvalidateRect(m_hwnd, NULL, FALSE);
  508. // Update the seek bar to match the current state.
  509. UpdateSeekBar();
  510. if (FAILED(hr))
  511. {
  512. NotifyError(m_hwnd, TEXT("Cannot open this file."), hr);
  513. }
  514. };
  515. //-----------------------------------------------------------------------------
  516. // MainWindow::OnFileOpen
  517. // Description: Open a new file for playback.
  518. //-----------------------------------------------------------------------------
  519. void MainWindow::OnFileOpen(INT nType)
  520. {
  521. OPENFILENAME ofn;
  522. ZeroMemory(&ofn, sizeof(ofn));
  523. WCHAR szFileName[MAX_PATH];
  524. szFileName[0] = L'\0';
  525. ofn.lStructSize = sizeof(ofn);
  526. ofn.hwndOwner = m_hwnd;
  527. ofn.hInstance = m_hInstance;
  528. ofn.lpstrFilter = L"All Files\0*.*\0\0";
  529. ofn.lpstrFile = szFileName;
  530. ofn.nMaxFile = MAX_PATH;
  531. ofn.Flags = OFN_FILEMUSTEXIST;
  532. HRESULT hr;
  533. if (GetOpenFileName(&ofn))
  534. {
  535. hr = m_pPlayer->OpenFile(szFileName, nType);
  536. // Update the state of the UI.
  537. UpdateUI();
  538. // Invalidate the application window, in case there is an old video
  539. // frame from the previous file and there is no video now. (eg, the
  540. // new file is audio only, or we failed to open this file.)
  541. InvalidateRect(m_hwnd, NULL, FALSE);
  542. // Update the seek bar to match the current state.
  543. UpdateSeekBar();
  544. if (SUCCEEDED(hr))
  545. {
  546. // If this file has a video stream, we need to notify
  547. // the VMR about the size of the destination rectangle.
  548. // Invoking our OnSize() handler does this.
  549. OnSize();
  550. }
  551. else
  552. {
  553. NotifyError(m_hwnd, TEXT("Cannot open this file."), hr);
  554. }
  555. }
  556. }
  557. //-----------------------------------------------------------------------------
  558. // MainWindow::OnPlay
  559. // Description: Start playback.
  560. //-----------------------------------------------------------------------------
  561. void MainWindow::OnPlay()
  562. {
  563. HRESULT hr = m_pPlayer->Play();
  564. UpdateUI();
  565. }
  566. //-----------------------------------------------------------------------------
  567. // MainWindow::OnStop
  568. // Description: Stop playback.
  569. //-----------------------------------------------------------------------------
  570. void MainWindow::OnStop()
  571. {
  572. HRESULT hr = m_pPlayer->Stop();
  573. // Seek back to the start.
  574. if (SUCCEEDED(hr))
  575. {
  576. if (m_pPlayer->CanSeek() || m_pPlayer->GetEncoder())
  577. {
  578. hr = m_pPlayer->SetPosition(0);
  579. }
  580. }
  581. UpdateUI();
  582. }
  583. //-----------------------------------------------------------------------------
  584. // MainWindow::OnPause
  585. // Description: Pause playback.
  586. //-----------------------------------------------------------------------------
  587. void MainWindow::OnPause()
  588. {
  589. HRESULT hr = m_pPlayer->Pause();
  590. UpdateUI();
  591. }
  592. //-----------------------------------------------------------------------------
  593. // MainWindow::OnMute
  594. // Description: Toggle the muted / unmuted state.
  595. //-----------------------------------------------------------------------------
  596. void MainWindow::OnMute()
  597. {
  598. if (m_pPlayer->IsMuted())
  599. {
  600. m_pPlayer->Mute(FALSE);
  601. toolbar.SetButtonImage(IDC_BUTTON_MUTE, ID_IMAGE_MUTE_OFF);
  602. }
  603. else
  604. {
  605. m_pPlayer->Mute(TRUE);
  606. toolbar.SetButtonImage(IDC_BUTTON_MUTE, ID_IMAGE_MUTE_ON);
  607. }
  608. }
  609. //-----------------------------------------------------------------------------
  610. // MainWindow::OnGraphEvent
  611. // Description: Callback to handle events from the filter graph.
  612. //-----------------------------------------------------------------------------
  613. // ! It is very important that the application does not tear down the graph inside this
  614. // callback.
  615. void MainWindow::OnGraphEvent(long eventCode, LONG_PTR param1, LONG_PTR param2)
  616. {
  617. switch (eventCode)
  618. {
  619. case EC_COMPLETE:
  620. OnStop();
  621. break;
  622. }
  623. }
  624. //-----------------------------------------------------------------------------
  625. // MainWindow::UpdateUI
  626. // Description: Update the UI based on the current playback state.
  627. //-----------------------------------------------------------------------------
  628. void MainWindow::UpdateUI()
  629. {
  630. BOOL bPlay = FALSE;
  631. BOOL bPause = FALSE;
  632. BOOL bStop = FALSE;
  633. switch (m_pPlayer->State())
  634. {
  635. case STATE_RUNNING:
  636. bPause = TRUE;
  637. bStop = TRUE;
  638. break;
  639. case STATE_PAUSED:
  640. bPlay = TRUE;
  641. bStop = TRUE;
  642. break;
  643. case STATE_STOPPED:
  644. bPlay = TRUE;
  645. break;
  646. }
  647. toolbar.Enable(IDC_BUTTON_PLAY, bPlay);
  648. toolbar.Enable(IDC_BUTTON_PAUSE, bPause);
  649. toolbar.Enable(IDC_BUTTON_STOP, bStop);
  650. HMENU hmenu = GetMenu(m_hwnd);
  651. HMENU subhmenu = GetSubMenu(hmenu, 1);
  652. if (m_pPlayer->GetEncoder())
  653. {
  654. EnableMenuItem(subhmenu, ID_CONFIGURE_ENCODER, MF_ENABLED);
  655. EnableMenuItem(subhmenu, ID_CONFIGURE_RENDER, MF_GRAYED);
  656. }
  657. else
  658. {
  659. EnableMenuItem(subhmenu, ID_CONFIGURE_ENCODER, MF_GRAYED);
  660. EnableMenuItem(subhmenu, ID_CONFIGURE_RENDER, MF_ENABLED);
  661. }
  662. }
  663. //-----------------------------------------------------------------------------
  664. // MainWindow::UpdateSeekBar
  665. // Description: Update the seekbar based on the current playback state.
  666. //-----------------------------------------------------------------------------
  667. void MainWindow::UpdateSeekBar()
  668. {
  669. // If the player can seek, set the seekbar range and start the time.
  670. // Otherwise, disable the seekbar.
  671. if (m_pPlayer->CanSeek())
  672. {
  673. seekbar.Enable(TRUE);
  674. LONGLONG rtDuration = 0;
  675. m_pPlayer->GetDuration(&rtDuration);
  676. seekbar.SetRange(0, (LONG)(rtDuration / ONE_MSEC));
  677. // Start the timer
  678. m_timerID = SetTimer(m_hwnd, IDT_TIMER1, TICK_FREQ, NULL);
  679. }
  680. else
  681. {
  682. seekbar.Enable(FALSE);
  683. // Stop the old timer, if any.
  684. StopTimer();
  685. }
  686. }
  687. //-----------------------------------------------------------------------------
  688. // MainWindow::StopTimer
  689. // Description: Stops the timer.
  690. //-----------------------------------------------------------------------------
  691. void MainWindow::StopTimer()
  692. {
  693. if (m_timerID != 0)
  694. {
  695. KillTimer(m_hwnd, m_timerID);
  696. m_timerID = 0;
  697. }
  698. }
  699. void NotifyError(HWND hwnd, TCHAR* sMessage, HRESULT hrStatus)
  700. {
  701. TCHAR sTmp[512];
  702. HRESULT hr = StringCchPrintf(sTmp, 512, TEXT("%s hr = 0x%X"), sMessage, hrStatus);
  703. if (SUCCEEDED(hr))
  704. {
  705. MessageBox(hwnd, sTmp, TEXT("Error"), MB_OK | MB_ICONERROR);
  706. }
  707. }