Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

943 lines
34 KiB

  1. //==========================================================================;
  2. //
  3. // vrsegimpl.h : additional infrastructure to support implementing IMSVidVRGraphSegment
  4. // nicely from c++
  5. // Copyright (c) Microsoft Corporation 1999-2000
  6. //
  7. /////////////////////////////////////////////////////////////////////////////
  8. #pragma once
  9. #ifndef VRSEGIMPL_H
  10. #define VRSEGIMPL_H
  11. #include "segimpl.h"
  12. #include "devices.h"
  13. #include <deviceeventimpl.h>
  14. namespace MSVideoControl {
  15. const int VIDCTL_NONMIXINGMODE = -1;
  16. const int VIDCTL_MIXINGMODE = 0;
  17. const int DEFAULT_MAX_STREAMS = 4; // dvd needs 3(video, cc, subpic) plus we want a spare
  18. #ifndef SPI_GETDROPSHADOW
  19. #define SPI_GETDROPSHADOW 0x1024
  20. #endif
  21. #ifndef SPI_SETDROPSHADOW
  22. #define SPI_SETDROPSHADOW 0x1025
  23. #endif
  24. #if 0
  25. const COLORKEY DEFAULT_COLOR_KEY = { CK_RGB, 0, 0xff00ff, 0xff00ff}; // magenta
  26. const AM_ASPECT_RATIO_MODE DEFAULT_ASPECT_RATIO_MODE = AM_ARMODE_STRETCHED;
  27. #else
  28. const OLE_COLOR DEFAULT_COLOR_KEY = 0xff00ff; // magenta
  29. const OLE_COLOR DEFAULT_BORDER_COLOR = 0x000000; // black
  30. #endif
  31. typedef CComQIPtr<IVMRWindowlessControl> PQWindowlessControl;
  32. typedef CComQIPtr<IPicture> PQIPic;
  33. typedef CComQIPtr<IPictureDisp> PQIPicDisp;
  34. typedef CComQIPtr<IVMRFilterConfig> PQVMRConfig;
  35. typedef CComQIPtr<IVMRSurfaceAllocator> PQVMRSAlloc;
  36. typedef CComQIPtr<IVMRImageCompositor> PQVMRImageComp;
  37. template<class T, class MostDerivedClass = IMSVidVRGraphSegment>
  38. class DECLSPEC_NOVTABLE IMSVidVRGraphSegmentImpl :
  39. public IMSVidGraphSegmentImpl<T, MSVidSEG_DEST, &GUID_NULL, MostDerivedClass> {
  40. protected:
  41. typedef IMSVidGraphSegmentImpl<T, MSVidSEG_DEST, &GUID_NULL, MostDerivedClass> basetype;
  42. IMSVidVRGraphSegmentImpl() :
  43. m_hOwner(INVALID_HWND),
  44. m_fUseOverlay(false),
  45. m_fVisible(false),
  46. m_iVideoRenderer(-1),
  47. m_rectDest(0, 0, 0, 0),
  48. m_rectSrc(0, 0, 0, 0),
  49. m_ColorKey(DEFAULT_COLOR_KEY),
  50. m_BorderColor(DEFAULT_BORDER_COLOR),
  51. m_fMaintainAspectRatio(true),
  52. m_fHaveOriginalSystemEffects(false),
  53. m_bDropShadows(false),
  54. m_bSmoothing(false),
  55. m_vmrMixing(true),
  56. m_Decimate(false),
  57. m_vmRendererMode(VMRMode_Renderless),
  58. m_compositorGuid(GUID_NULL),
  59. m_APid(-1),
  60. m_vidSuppressEffects(true)
  61. {}
  62. PQVMRImageComp ImCompositor;
  63. GUID2 m_compositorGuid;
  64. HWND m_hOwner;
  65. bool m_fUseOverlay;
  66. bool m_fVisible;
  67. CRect m_rectSrc;
  68. CRect m_rectDest;
  69. PQVMRConfig m_pVMR;
  70. PQVMRWindowlessControl m_pVMRWC;
  71. int m_iVideoRenderer;
  72. OLE_COLOR m_ColorKey;
  73. OLE_COLOR m_BorderColor;
  74. BOOL m_bSmoothing;
  75. BOOL m_bDropShadows;
  76. bool m_fHaveOriginalSystemEffects;
  77. bool m_fMaintainAspectRatio;
  78. LONG m_vmRendererMode;
  79. bool m_vmrMixing;
  80. BOOL m_Decimate;
  81. PQVMRSAlloc qiSurfAlloc;
  82. long m_APid;
  83. bool m_vidSuppressEffects;
  84. public:
  85. virtual ~IMSVidVRGraphSegmentImpl() {}
  86. void DisableAPM() {
  87. SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
  88. }
  89. void EnableAPM() {
  90. SetThreadExecutionState(ES_CONTINUOUS);
  91. }
  92. HRESULT Unload(void) {
  93. IMSVidGraphSegmentImpl<CMSVidVideoRenderer, MSVidSEG_DEST, &GUID_NULL>::Unload();
  94. m_iVideoRenderer = -1;
  95. }
  96. HRESULT UpdatePos() {
  97. if(!m_pVMRWC){
  98. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  99. }
  100. CRect s(m_rectSrc), d(m_rectDest);
  101. if (!s ||
  102. !m_fVisible ||
  103. m_hOwner == INVALID_HWND ||
  104. !::IsWindow(m_hOwner) ||
  105. !d.Width() ||
  106. !d.Height()) {
  107. d = CRect();
  108. }
  109. if (!d) {
  110. s = CRect();
  111. }
  112. #if 0
  113. if (d && m_hOwner != INVALID_HWND) {
  114. ::MapWindowPoints(GetDesktopWindow(), m_hOwner, reinterpret_cast<LPPOINT>(&d), 2);
  115. }
  116. #endif
  117. TRACELSM(TRACE_PAINT, (dbgDump << "VRSegimpl::UpdatePos() s = " << s << " d = " << d), "");
  118. #if 0
  119. PUnknown vidUnknown(m_pContainer);
  120. DWORD Temp_id = (DWORD_PTR)(vidUnknown.p);
  121. if(m_APid == Temp_id){
  122. #endif
  123. return m_pVMRWC->SetVideoPosition(s, d);
  124. #if 0
  125. }
  126. else{
  127. return NO_ERROR;
  128. }
  129. #endif
  130. }
  131. virtual HRESULT SetVRConfig() {
  132. if (m_pVMR) {
  133. HRESULT hr;
  134. DWORD dwRenderPrefs = 0;
  135. if (m_fUseOverlay) {
  136. if(m_vidSuppressEffects){
  137. if (!m_fHaveOriginalSystemEffects) {
  138. if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &m_bSmoothing, 0)) {
  139. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::SetVRConfig() can't get original drop shadows rc = " << GetLastError()), "");
  140. }
  141. if (!SystemParametersInfo(SPI_GETDROPSHADOW, 0, &m_bDropShadows, 0)) {
  142. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::SetVRConfig() can't get original font smoothing rc = " << GetLastError()), "");
  143. }
  144. m_fHaveOriginalSystemEffects = true;
  145. }
  146. BOOL val = FALSE;
  147. if (!SystemParametersInfo(SPI_SETDROPSHADOW, 0, IntToPtr(FALSE), 0)) { // only send change notice once on the last one
  148. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::SetVRConfig() can't turn off font smoothing rc = " << GetLastError()), "");
  149. }
  150. if (!SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)) {
  151. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::SetVRConfig() can't turn off font smoothing rc = " << GetLastError()), "");
  152. }
  153. }
  154. dwRenderPrefs = /*RenderPrefs_ForceOverlays |*/ RenderPrefs_DoNotRenderColorKeyAndBorder;
  155. TRACELM(TRACE_DETAIL, "IMSVidGraphSegmentImpl::SetVRConfig() forcing overlays");
  156. } else {
  157. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidGraphSegmentImpl::SetVRConfig() border color = " << hexdump(m_BorderColor)), "");
  158. if(m_pVMRWC){
  159. hr = m_pVMRWC->SetBorderColor(m_BorderColor);
  160. if (FAILED(hr)) {
  161. return hr;
  162. }
  163. }
  164. dwRenderPrefs = RenderPrefs_ForceOffscreen; // no overlays allowed
  165. }
  166. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidGraphSegmentImpl::SetVRConfig() rprefs = " << hexdump(dwRenderPrefs)), "");
  167. hr = m_pVMR->SetRenderingPrefs(dwRenderPrefs);
  168. if (FAILED(hr)) {
  169. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::SetVRConfig() can't set vmr rendering prefs: hr = " << std::hex << hr), "");
  170. return E_UNEXPECTED;
  171. }
  172. #if 0
  173. hr = m_pVMR->SetBorderColor(0x0101ff);
  174. // hr = m_pVMR->SetBorderColor(m_BorderColor);
  175. if (FAILED(hr)) {
  176. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::SetVRConfig() border hack failed hr = " << hexdump(hr)), "");
  177. }
  178. #endif
  179. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidGraphSegmentImpl::SetVRConfig() armode = " << (m_fMaintainAspectRatio ? "VMR_ARMODE_LETTER_BOX" : "VMR_ARMODE_NONE")), "");
  180. if(m_pVMRWC){
  181. if (m_fUseOverlay) {
  182. // if we're doing the colorkey and all that then don't let the vmr
  183. // do letterboxing because we get rounding errors which causes
  184. // colorkey colored lines around the edges
  185. hr = m_pVMRWC->SetAspectRatioMode(VMR_ARMODE_NONE);
  186. if (FAILED(hr)) {
  187. return hr;
  188. }
  189. } else {
  190. hr = m_pVMRWC->SetAspectRatioMode(m_fMaintainAspectRatio ? VMR_ARMODE_LETTER_BOX : VMR_ARMODE_NONE);
  191. if (FAILED(hr)) {
  192. return hr;
  193. }
  194. }
  195. }
  196. // compositor should be set regardless of whether or not we're using overlays
  197. CComQIPtr<IVMRImageCompositor> IVMRICptr(ImCompositor);
  198. if(IVMRICptr){
  199. hr = m_pVMR->SetImageCompositor(IVMRICptr);
  200. if(FAILED(hr)){
  201. TRACELSM(TRACE_ERROR, (dbgDump << "SetVRConfig() SetImageCompositor failed hr = " << hexdump(hr)), "");
  202. return hr;
  203. }
  204. }
  205. if (!m_rectSrc) {
  206. CSize s, a;
  207. hr = get_NativeSize(&s, &a);
  208. if (FAILED(hr)) {
  209. return hr;
  210. }
  211. m_rectSrc = CRect(CPoint(0, 0), s);
  212. }
  213. hr = UpdatePos();
  214. if (FAILED(hr)) {
  215. return hr;
  216. }
  217. // reminder: color key is set by override in video renderer derived class after we return to it
  218. if (m_hOwner != INVALID_HWND && ::IsWindow(m_hOwner)) {
  219. if(m_pVMRWC){
  220. #if 0
  221. // stop state race condition temp fix
  222. PUnknown vidUnknown(m_pContainer);
  223. DWORD Temp_id = (DWORD_PTR)(vidUnknown.p);
  224. if(m_APid == Temp_id){
  225. #endif
  226. hr = m_pVMRWC->SetVideoClippingWindow(m_hOwner);
  227. if (FAILED(hr)) {
  228. TRACELSM(TRACE_ERROR, (dbgDump << "SetVRConfig() SetClipWnd failed hr = " << hexdump(hr)), "");
  229. return hr;
  230. }
  231. #if 0
  232. }
  233. #endif
  234. }
  235. }
  236. }
  237. return NOERROR;
  238. }
  239. STDMETHOD(CheckVMRMode)(){
  240. try{
  241. PQVidCtl pqCtl;
  242. HRESULT hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast<void**>(&pqCtl));
  243. if(FAILED(hr)){
  244. return hr;
  245. }
  246. PQInputDevice pqIDev;
  247. hr = pqCtl->get_InputActive(&pqIDev);
  248. if(FAILED(hr)){
  249. return E_UNEXPECTED;
  250. }
  251. GUID2 inputID, classID;
  252. hr = pqIDev->get__ClassID(&inputID);
  253. if(FAILED(hr)){
  254. return hr;
  255. }
  256. if(inputID == CLSID_MSVidBDATunerDevice){
  257. PQFeatures pF;
  258. hr = pqCtl->get_FeaturesActive(&pF);
  259. if (FAILED(hr)) {
  260. return hr;
  261. }
  262. CFeatures* pC = static_cast<CFeatures *>(pF.p);
  263. for (DeviceCollection::iterator i = pC->m_Devices.begin(); i != pC->m_Devices.end(); ++i) {
  264. PQFeature f(*i);
  265. hr = f->get__ClassID(&classID);
  266. if (FAILED(hr)) {
  267. // TRACELM(TRACE_ERROR, "CTVProt::GetVidCtl() Can't get feature class id");
  268. continue;
  269. }
  270. if (classID == CLSID_MSVidClosedCaptioning) {
  271. break;
  272. }
  273. }
  274. if(classID == CLSID_MSVidClosedCaptioning){
  275. if(!m_vmrMixing){
  276. hr = put__VMRendererMode(VIDCTL_MIXINGMODE);
  277. }
  278. }
  279. else{
  280. if(m_vmrMixing){
  281. hr = put__VMRendererMode(VIDCTL_NONMIXINGMODE);
  282. }
  283. }
  284. if(FAILED(hr)){
  285. return E_UNEXPECTED;
  286. }
  287. }
  288. else{
  289. if(!m_vmrMixing){
  290. hr = put__VMRendererMode(VIDCTL_MIXINGMODE);
  291. if(FAILED(hr)){
  292. return E_UNEXPECTED;
  293. }
  294. }
  295. }
  296. return NOERROR;
  297. }
  298. catch(...){
  299. return E_UNEXPECTED;
  300. }
  301. }
  302. // IGraphSegment
  303. STDMETHOD(put_Container)(IMSVidGraphSegmentContainer *pCtl) {
  304. try {
  305. HRESULT hr = IMSVidGraphSegmentImpl<T, MSVidSEG_DEST, &GUID_NULL, MostDerivedClass>::put_Container(pCtl);
  306. if (FAILED(hr)) {
  307. return hr;
  308. }
  309. if(pCtl){
  310. hr = CheckVMRMode();
  311. if(FAILED(hr)){
  312. return hr;
  313. }
  314. }
  315. return NOERROR;
  316. } catch(...) {
  317. return E_UNEXPECTED;
  318. }
  319. }
  320. STDMETHOD(CleanupVMR)(){
  321. try{
  322. HRESULT hr = S_OK;
  323. if(m_pVMR){
  324. if(m_pContainer){
  325. CComQIPtr<IMSVidCtl> pq_vidCtl;
  326. hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast<void**>(&pq_vidCtl));
  327. if(FAILED(hr)){
  328. return hr;
  329. }
  330. MSVidCtlStateList state;
  331. hr = pq_vidCtl->get_State(&state);
  332. if(FAILED(hr)){
  333. return hr;
  334. }
  335. if(state != STATE_UNBUILT){
  336. hr = pq_vidCtl->Stop();
  337. if(FAILED(hr)){
  338. return hr;
  339. }
  340. hr = pq_vidCtl->Decompose();
  341. if(FAILED(hr)){
  342. return hr;
  343. }
  344. }
  345. DSFilter vr(m_pVMR);
  346. m_pGraph->RemoveFilter(vr);
  347. vr.Release();
  348. m_Filters.clear();
  349. m_iVideoRenderer = -1;
  350. }
  351. CComQIPtr<IVMRSurfaceAllocatorNotify>qiSan;
  352. qiSan = m_pVMR;
  353. if(!qiSan){
  354. _ASSERT(false);
  355. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::CleanupVMR() can't qi for surface allocator notify: hr = " << std::hex << hr), "");
  356. }
  357. else{
  358. hr = qiSan->AdviseSurfaceAllocator(m_APid, NULL);
  359. if(FAILED(hr)){
  360. _ASSERT(false);
  361. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::CleanupVMR() advise surface allocator (NULL) failed: hr = " << std::hex << hr), "");
  362. }
  363. qiSan.Release();
  364. if (qiSurfAlloc) {
  365. hr = qiSurfAlloc->AdviseNotify(NULL);
  366. }
  367. }
  368. m_pVMRWC.Release();
  369. qiSurfAlloc.Release();
  370. m_pVMR.Release();
  371. _ASSERT(!m_pVMR);
  372. }
  373. }
  374. catch(...){
  375. return E_UNEXPECTED;
  376. }
  377. return S_OK;
  378. }
  379. STDMETHOD(Build)() {
  380. TRACELM(TRACE_DETAIL, "IMSVidVRGraphSegmentImpl::Build()");
  381. if (!m_fInit || !m_pGraph) {
  382. return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVRGraphSegment), CO_E_NOTINITIALIZED);
  383. }
  384. try {
  385. CString csName;
  386. if (!m_pVMR) {
  387. HRESULT hr = m_pVMR.CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER);
  388. if (FAILED(hr)) {
  389. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't load vmr: hr = " << std::hex << hr), "");
  390. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  391. }
  392. // Here is what is going on
  393. // We are not putting the vmr into renderless mode and passing in the default allocator/presenter
  394. // This is to support the use of custom allocator/presenters
  395. hr = m_pVMR->SetRenderingMode(m_vmRendererMode);
  396. if (FAILED(hr)) {
  397. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't set vmr rendering mode: hr = " << std::hex << hr), "");
  398. return ImplReportError(__uuidof(T), IDS_CANT_SET_VR_DEFAULTS, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  399. }
  400. // If we are in mixing mode, do that which needs to be done
  401. if(m_vmrMixing){
  402. hr = m_pVMR->SetNumberOfStreams(DEFAULT_MAX_STREAMS);
  403. if (FAILED(hr)) {
  404. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't set vmr stream count: hr = " << std::hex << hr), "");
  405. return ImplReportError(__uuidof(T), IDS_CANT_SET_VR_DEFAULTS, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  406. }
  407. DWORD curPrefs;
  408. DWORD deci;
  409. CComQIPtr<IVMRMixerControl>PQIVMRMixer(m_pVMR);
  410. if(!PQIVMRMixer){
  411. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't get vmr mixer control: hr = " << std::hex << hr), "");
  412. return E_UNEXPECTED;
  413. }
  414. hr = PQIVMRMixer->GetMixingPrefs(&curPrefs);
  415. if(FAILED(hr)){
  416. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't get vmr mixer prefs: hr = " << std::hex << hr), "");
  417. return hr;
  418. }
  419. deci = (m_Decimate?MixerPref_DecimateOutput:MixerPref_NoDecimation);
  420. if(!(curPrefs&deci)){
  421. curPrefs = (curPrefs&(~MixerPref_DecimateMask))|deci;
  422. hr = PQIVMRMixer->SetMixingPrefs(curPrefs);
  423. if(FAILED(hr)){
  424. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't set vmr mixer prefs: hr = " << std::hex << hr), "");
  425. return hr;
  426. }
  427. }
  428. }
  429. // Set up the allocator presenter
  430. if(!qiSurfAlloc){
  431. hr = qiSurfAlloc.CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER);
  432. if(FAILED(hr)){
  433. _ASSERT(false);
  434. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't cocreate default surface allocator : hr = " << std::hex << hr), "");
  435. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  436. }
  437. }
  438. CComQIPtr<IVMRSurfaceAllocatorNotify>qiSan;
  439. qiSan = m_pVMR;
  440. if(!qiSan){
  441. _ASSERT(false);
  442. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't qi for surface allocator notify: hr = " << std::hex << hr), "");
  443. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  444. }
  445. if(m_APid == -1){
  446. PUnknown vidUnknown(m_pContainer);
  447. m_APid = (DWORD_PTR)(vidUnknown.p);
  448. }
  449. hr = qiSan->AdviseSurfaceAllocator(m_APid, qiSurfAlloc);
  450. if(FAILED(hr)){
  451. _ASSERT(false);
  452. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't set surface allocator: hr = " << std::hex << hr), "");
  453. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  454. }
  455. hr = qiSurfAlloc->AdviseNotify(qiSan);
  456. if(FAILED(hr)){
  457. _ASSERT(false);
  458. TRACELSM(TRACE_ERROR, (dbgDump << "IMSVidGraphSegmentImpl::Build() can't advise notify: hr = " << std::hex << hr), "");
  459. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IVMRWindowlessControl), E_UNEXPECTED);
  460. }
  461. // Windowless control comes from alloc/presenter (vmr just proxys it through in the windowless case
  462. // so this should act exactly like being in windless mode
  463. m_pVMRWC = qiSurfAlloc;
  464. }
  465. DSFilter vr(m_pVMR);
  466. if (!vr) {
  467. ASSERT(false);
  468. return ImplReportError(__uuidof(T), IDS_CANT_CREATE_FILTER, __uuidof(IBaseFilter), E_UNEXPECTED);
  469. }
  470. if (m_iVideoRenderer == -1) {
  471. m_Filters.push_back(vr);
  472. csName = _T("Video Mixing Renderer");
  473. m_pGraph.AddFilter(vr, csName);
  474. }
  475. m_iVideoRenderer = 0;
  476. ASSERT(m_iVideoRenderer == 0);
  477. SetVRConfig(); // ignore errors, we'll try again at run time
  478. return NOERROR;
  479. } catch (ComException &e) {
  480. return e;
  481. } catch (...) {
  482. return E_UNEXPECTED;
  483. }
  484. }
  485. STDMETHOD(PreRun)() {
  486. try {
  487. if (!m_pVMR) {
  488. return HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  489. }
  490. m_rectDest = CRect(0, 0, 0, 0);
  491. m_rectSrc = CRect(0, 0, 0, 0);
  492. if(m_vidSuppressEffects){
  493. DisableAPM();
  494. }
  495. HRESULT hr = UpdatePos();
  496. if (FAILED(hr)) {
  497. return hr;
  498. }
  499. return SetVRConfig();
  500. } catch (ComException &e) {
  501. return e;
  502. } catch (...) {
  503. return E_UNEXPECTED;
  504. }
  505. }
  506. STDMETHOD(PostStop)() {
  507. try {
  508. m_rectDest = CRect(0, 0, 0, 0);
  509. m_rectSrc = CRect(0, 0, 0, 0);
  510. if (m_fHaveOriginalSystemEffects) {
  511. if (!SystemParametersInfo(SPI_SETDROPSHADOW, 0, &m_bDropShadows, 0)) { // only send change notice once on the last one
  512. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::SetVRConfig() can't turn off drop shadows rc = " << GetLastError()), "");
  513. }
  514. if (!SystemParametersInfo(SPI_SETFONTSMOOTHING, m_bSmoothing, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)) {
  515. TRACELSM(TRACE_ERROR, (dbgDump << "VRSegimpl::PostStop() can't restore font smoothing rc = " << GetLastError()), "");
  516. }
  517. }
  518. EnableAPM();
  519. return put_Visible(VARIANT_FALSE);
  520. } catch (...) {
  521. ASSERT(FALSE);
  522. return E_UNEXPECTED;
  523. }
  524. }
  525. // IMSVidVRGraphSegment
  526. STDMETHOD(put__VMRendererMode)(/*[in]*/ LONG dwMode){
  527. try{
  528. bool changed, mMode;
  529. changed = false;
  530. HRESULT hr = S_OK;
  531. CString csName;
  532. if (dwMode == VIDCTL_NONMIXINGMODE || dwMode == VIDCTL_MIXINGMODE){
  533. mMode = (dwMode==VIDCTL_MIXINGMODE)?true:false;
  534. if(mMode != m_vmrMixing){
  535. m_vmrMixing = mMode;
  536. changed = true;
  537. }
  538. }
  539. else{
  540. return E_FAIL;
  541. }
  542. if(changed){
  543. hr = CleanupVMR();
  544. return hr;
  545. }
  546. else{
  547. return NOERROR;
  548. }
  549. }
  550. catch(HRESULT hres){
  551. return hres;
  552. }
  553. catch(...){
  554. return E_UNEXPECTED;
  555. }
  556. }
  557. STDMETHOD(get_Owner)(/*[out, retval]*/ HWND* phWnd) {
  558. try {
  559. if (!phWnd) {
  560. return E_POINTER;
  561. }
  562. *phWnd = m_hOwner;
  563. return NOERROR;
  564. } catch(...) {
  565. return E_UNEXPECTED;
  566. }
  567. }
  568. STDMETHOD(put_Owner)(/*[in]*/ HWND hWnd) {
  569. try {
  570. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidVRGraphSegmentImpl<>::put_Owner() hWnd= " << hexdump(reinterpret_cast<ULONG_PTR>(hWnd))), "");
  571. if (m_hOwner == hWnd) {
  572. return NOERROR;
  573. }
  574. if (m_iVideoRenderer == -1 || !m_Filters[m_iVideoRenderer] || !m_pGraph || !m_pVMR) {
  575. return NOERROR;
  576. }
  577. m_hOwner = hWnd;
  578. if (m_hOwner != INVALID_HWND) {
  579. if(m_pVMRWC){
  580. #if 0
  581. // stop state race condition temp fix
  582. PUnknown vidUnknown(m_pContainer);
  583. DWORD Temp_id = (DWORD_PTR)(vidUnknown.p);
  584. if(m_APid == Temp_id){
  585. #endif
  586. HRESULT hr = m_pVMRWC->SetVideoClippingWindow(m_hOwner);
  587. if (FAILED(hr)) {
  588. TRACELSM(TRACE_ERROR, (dbgDump << "put_Owner() SetClipWnd failed hr = " << hexdump(hr)), "");
  589. return hr;
  590. }
  591. #if 0
  592. }
  593. #endif
  594. }
  595. }
  596. return UpdatePos(); // force a refresh if we're changing clip rects
  597. } catch(...) {
  598. return E_UNEXPECTED;
  599. }
  600. }
  601. STDMETHOD(get_UseOverlay)(/*[out, retval]*/ VARIANT_BOOL *fUseOverlay) {
  602. try {
  603. if (!fUseOverlay) {
  604. return E_POINTER;
  605. }
  606. *fUseOverlay = m_fUseOverlay ? VARIANT_TRUE : VARIANT_FALSE;
  607. } catch(...) {
  608. return E_POINTER;
  609. }
  610. return NOERROR;
  611. }
  612. STDMETHOD(put_UseOverlay)(/*[in]*/ VARIANT_BOOL fUseOverlayVal) {
  613. try {
  614. TRACELSM(TRACE_PAINT, (dbgDump << "VRSegimpl::put_UseOverlay() use_overlay = " << fUseOverlayVal), "");
  615. bool fUseOverlay = (fUseOverlayVal == VARIANT_TRUE);
  616. if (fUseOverlay == m_fUseOverlay) {
  617. return NOERROR;
  618. }
  619. m_fUseOverlay = fUseOverlay;
  620. if (!m_pVMR) {
  621. return NOERROR;
  622. }
  623. return SetVRConfig();
  624. } catch(...) {
  625. return E_POINTER;
  626. }
  627. }
  628. // from top-level control visibility state
  629. STDMETHOD(get_Visible)(/*[out, retval]*/ VARIANT_BOOL* fVisible) {
  630. try {
  631. if (!fVisible) {
  632. return E_POINTER;
  633. }
  634. *fVisible = m_fVisible ? VARIANT_TRUE : VARIANT_FALSE;
  635. } catch(...) {
  636. return E_POINTER;
  637. }
  638. return NOERROR;
  639. }
  640. STDMETHOD(put_Visible)(/*[in]*/ VARIANT_BOOL fVisibleVal) {
  641. try {
  642. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidVRGraphSegmentImpl<>::put_Visible() fV = " << fVisibleVal), "");
  643. bool fVisible = (fVisibleVal == VARIANT_TRUE);
  644. if (fVisible == m_fVisible) {
  645. return NOERROR;
  646. }
  647. m_fVisible = fVisible;
  648. if (!m_pGraph || m_pGraph.GetState() == State_Stopped || m_iVideoRenderer == -1 || !m_pVMR) {
  649. return NOERROR;
  650. }
  651. HRESULT hr = UpdatePos();
  652. if (FAILED(hr)) {
  653. return hr;
  654. }
  655. if (!!m_pGraph && m_pGraph.IsPlaying()) {
  656. if (m_fVisible) {
  657. if(m_vidSuppressEffects){
  658. DisableAPM();
  659. }
  660. } else {
  661. EnableAPM();
  662. }
  663. }
  664. return NOERROR;
  665. } catch(ComException &e) {
  666. return e;
  667. } catch(...) {
  668. return E_UNEXPECTED;
  669. }
  670. }
  671. STDMETHOD(get_Source)(/*[out, retval]*/ LPRECT pRect) {
  672. try {
  673. if (!pRect) {
  674. return E_POINTER;
  675. }
  676. *pRect = m_rectSrc;
  677. return NOERROR;
  678. } catch(...) {
  679. return E_UNEXPECTED;
  680. }
  681. }
  682. STDMETHOD(put_Source)(/*[in]*/ RECT pRect) {
  683. try {
  684. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidVRGraphSegmentImpl<>::put_Source() r = " << pRect), "");
  685. if (m_rectSrc == pRect) {
  686. return NOERROR;
  687. }
  688. if (m_iVideoRenderer == -1 || !m_Filters[m_iVideoRenderer] || !m_pGraph || !m_pVMR) {
  689. return NOERROR;
  690. }
  691. m_rectSrc = pRect;
  692. return UpdatePos();
  693. } catch(...) {
  694. return E_UNEXPECTED;
  695. }
  696. }
  697. STDMETHOD(get_Destination)(/*[out, retval]*/ LPRECT pRect) {
  698. try {
  699. if (!pRect) {
  700. return E_POINTER;
  701. }
  702. *pRect = m_rectDest;
  703. return NOERROR;
  704. } catch(...) {
  705. return E_UNEXPECTED;
  706. }
  707. }
  708. STDMETHOD(put_Destination)(/*[in]*/ RECT pRect) {
  709. try {
  710. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidVRGraphSegmentImpl<>::put_Dest() r = " << pRect), "");
  711. if (m_rectDest == pRect) {
  712. return NOERROR;
  713. }
  714. if (m_iVideoRenderer == -1 || !m_Filters[m_iVideoRenderer] || !m_pGraph || !m_pVMR) {
  715. return NOERROR;
  716. }
  717. TRACELM(TRACE_DETAIL, "IMSVidVRGraphSegmentImpl<>::put_Dest() setting");
  718. m_rectDest = pRect;
  719. return UpdatePos();
  720. } catch(...) {
  721. return E_UNEXPECTED;
  722. }
  723. }
  724. STDMETHOD(get_NativeSize)(/*[out]*/ LPSIZE pSize, LPSIZE pAR) {
  725. try {
  726. if (!pSize) {
  727. return E_POINTER;
  728. }
  729. if (m_iVideoRenderer == -1 || !m_Filters[m_iVideoRenderer] || !m_pGraph || !m_pVMR) {
  730. *pSize = CSize(0, 0);
  731. return NOERROR;
  732. }
  733. if(m_pVMRWC){
  734. HRESULT hr = m_pVMRWC->GetNativeVideoSize(&pSize->cx, &pSize->cy, &pAR->cx, &pAR->cy);
  735. if (FAILED(hr)) {
  736. return hr;
  737. }
  738. }
  739. else{
  740. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  741. }
  742. return NOERROR;
  743. } catch(...) {
  744. return E_UNEXPECTED;
  745. }
  746. }
  747. // from top-level control refresh method
  748. STDMETHOD(Refresh)() {
  749. try {
  750. if (!m_pVMR) {
  751. return NOERROR;
  752. }
  753. HRESULT hr = SetVRConfig();
  754. if (FAILED(hr)) {
  755. return hr;
  756. }
  757. hr = UpdatePos();
  758. if (FAILED(hr)) {
  759. return hr;
  760. }
  761. return NOERROR;
  762. } catch(...) {
  763. return E_UNEXPECTED;
  764. }
  765. }
  766. STDMETHOD(DisplayChange)() {
  767. if (m_pVMR) {
  768. if(m_pVMRWC){
  769. return m_pVMRWC->DisplayModeChanged();
  770. }
  771. }
  772. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  773. }
  774. STDMETHOD(RePaint)(HDC hdc) {
  775. if (m_pVMR) {
  776. if(m_pVMRWC){
  777. return m_pVMRWC->RepaintVideo(m_hOwner, hdc);
  778. }
  779. }
  780. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  781. }
  782. // IMSVidVRSegment
  783. STDMETHOD(get_ColorKey)(OLE_COLOR* pColorKey) {
  784. try {
  785. if (!pColorKey) {
  786. return E_POINTER;
  787. }
  788. *pColorKey = m_ColorKey;
  789. return NOERROR;
  790. } catch(...) {
  791. return E_UNEXPECTED;
  792. }
  793. }
  794. STDMETHOD(put_ColorKey)(OLE_COLOR ColorKey) {
  795. try {
  796. if (m_ColorKey == ColorKey) {
  797. return NOERROR;
  798. }
  799. m_ColorKey = ColorKey;
  800. if (!m_pVMR) {
  801. return NOERROR;
  802. }
  803. if(m_pVMRWC){
  804. return m_pVMRWC->SetColorKey(m_ColorKey);
  805. }
  806. else{
  807. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  808. }
  809. } catch(...) {
  810. return E_UNEXPECTED;
  811. }
  812. }
  813. STDMETHOD(get_BorderColor)(OLE_COLOR* pBorderColor) {
  814. try {
  815. if (!pBorderColor) {
  816. return E_POINTER;
  817. }
  818. *pBorderColor = m_BorderColor;
  819. return NOERROR;
  820. } catch(...) {
  821. return E_UNEXPECTED;
  822. }
  823. }
  824. STDMETHOD(put_BorderColor)(OLE_COLOR BorderColor) {
  825. try {
  826. if (m_BorderColor == BorderColor) {
  827. return NOERROR;
  828. }
  829. m_BorderColor = BorderColor;
  830. if (!m_pVMR) {
  831. return NOERROR;
  832. }
  833. if(m_pVMRWC){
  834. return m_pVMRWC->SetBorderColor(m_BorderColor);
  835. }
  836. else{
  837. return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), S_FALSE);
  838. }
  839. } catch(...) {
  840. return E_UNEXPECTED;
  841. }
  842. }
  843. STDMETHOD(get_MaintainAspectRatio)(/*[out, retval]*/ VARIANT_BOOL* fMaintainAspectRatio) {
  844. try {
  845. if (!fMaintainAspectRatio) {
  846. return E_POINTER;
  847. }
  848. *fMaintainAspectRatio = m_fMaintainAspectRatio ? VARIANT_TRUE : VARIANT_FALSE;
  849. } catch(...) {
  850. return E_POINTER;
  851. }
  852. return NOERROR;
  853. }
  854. STDMETHOD(put_MaintainAspectRatio)(/*[in]*/ VARIANT_BOOL fMaintainAspectRatioVal) {
  855. try {
  856. TRACELSM(TRACE_DETAIL, (dbgDump << "IMSVidVRGraphSegmentImpl<>::put_MaintainAspectRatio() fV = " << fMaintainAspectRatioVal), "");
  857. bool fMaintainAspectRatio = (fMaintainAspectRatioVal == VARIANT_TRUE);
  858. if (fMaintainAspectRatio == m_fMaintainAspectRatio) {
  859. return NOERROR;
  860. }
  861. m_fMaintainAspectRatio = fMaintainAspectRatio;
  862. if (!m_pGraph || m_pGraph.GetState() == State_Stopped || m_iVideoRenderer == -1 || !m_pVMR) {
  863. return NOERROR;
  864. }
  865. HRESULT hr = SetVRConfig();
  866. if (FAILED(hr)) {
  867. return hr;
  868. }
  869. return NOERROR;
  870. } catch(ComException &e) {
  871. return e;
  872. } catch(...) {
  873. return E_UNEXPECTED;
  874. }
  875. }
  876. };
  877. template <class T, const IID* piid, class CDV = CComDynamicUnkArray>
  878. class CProxy_VRSeg : public CProxy_DeviceEvent<T, piid, CDV>
  879. {
  880. public:
  881. VOID Fire_OverlayUnavailable()
  882. {
  883. Fire_VoidMethod(eventidOverlayUnavailable);
  884. }
  885. };
  886. typedef CComQIPtr<IMSVidVRGraphSegment> PQVRGraphSegment;
  887. }; // namespace
  888. #endif
  889. // end of file - vrsegimpl.h