Leaked source code of windows server 2003
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.

1979 lines
80 KiB

  1. //==========================================================================;
  2. //
  3. // Copyright (c) Microsoft Corporation 1995-2000.
  4. //
  5. //--------------------------------------------------------------------------;
  6. //
  7. // dsextend.cpp : implementation of various direct show extension classes
  8. //
  9. #include "stdafx.h"
  10. #ifndef TUNING_MODEL_ONLY
  11. #include "ksextend.h"
  12. #include "dsextend.h"
  13. const int MAX_OCCURRENCE_COUNT = 2;
  14. static DWORD dwFetch;
  15. #if 0
  16. // note: the compiler is generating but never calling the code to construct these initializers so the pointers
  17. // are staying null. we work around this by providing a function which dynamically allocating them on the heap
  18. // and calling it in our dllmain.
  19. // DSGraphContainer
  20. std_arity1pmf<IGraphBuilder, IEnumFilters **, HRESULT> * DSGraphContainer::Fetch = &std_arity1pmf<IGraphBuilder, IEnumFilters **, HRESULT>(&IGraphBuilder::EnumFilters);
  21. std_arity0pmf<IEnumFilters, HRESULT> * DSGraphContainer::iterator::Reset = &std_arity0_member(&IEnumFilters::Reset);
  22. std_arity1pmf<IEnumFilters, IBaseFilter **, HRESULT> * DSGraphContainer::iterator::Next = &std_bind_mf_1_3(std_arity3_member(&IEnumFilters::Next), 1, &dwFetch);
  23. // DSFilter
  24. std_arity1pmf<IBaseFilter, IEnumPins **, HRESULT> * DSFilter::Fetch = &std_arity1_member(&IBaseFilter::EnumPins);
  25. std_arity0pmf<IEnumPins, HRESULT> * DSFilter::iterator::Reset = &std_arity0_member(&IEnumPins::Reset);
  26. std_arity1pmf<IEnumPins, IPin **, HRESULT> * DSFilter::iterator::Next = &std_bind_mf_1_3(std_arity3_member(&IEnumPins::Next), 1, &dwFetch);
  27. // DSDevices
  28. std_arity1pmf<ICreateDevEnum, IEnumMoniker **, HRESULT> * DSDeviceSequence::Fetch = NULL; // no arity0 fetch actually exists. overridden with bound functor in DSDeviceSequence::GetFetch
  29. std_arity0pmf<IEnumMoniker, HRESULT> * DSDevices::iterator::Reset = &std_arity0_member(&IEnumMoniker::Reset);
  30. std_arity1pmf<IEnumMoniker, IMoniker **, HRESULT> * DSDevices::iterator::Next = &std_bind_mf_1_3(std_arity3_member(&IEnumMoniker::Next), 1, &dwFetch);
  31. // DSFilterMapper
  32. std_arity1pmf<IFilterMapper2, IEnumMoniker **, HRESULT> * DSFilterMapperSequence::Fetch = NULL;// no arity0 fetch actually exists. overridden with bound functor in DSFilterMapperSequence::GetFetch
  33. // uses same types as DSDevices so its the same template expansion, already initialized
  34. // DSPin
  35. std_arity1pmf<IPin, IEnumMediaTypes **, HRESULT> * DSPin::Fetch = &std_arity1_member(&IPin::EnumMediaTypes);
  36. std_arity0pmf<IEnumMediaTypes, HRESULT> * DSPin::iterator::Reset = &std_arity0_member(&IEnumMediaTypes::Reset);
  37. std_arity1pmf<IEnumMediaTypes, AM_MEDIA_TYPE **, HRESULT> * DSPin::iterator::Next = &std_bind_mf_1_3(std_arity3_member(&IEnumMediaTypes::Next), 1, &dwFetch);
  38. #else
  39. // DSGraphContainer
  40. std_arity1pmf<IGraphBuilder, IEnumFilters **, HRESULT> * DSGraphContainer::Fetch = NULL;
  41. std_arity0pmf<IEnumFilters, HRESULT> * DSGraphContainer::iterator::Reset = NULL;
  42. std_arity1pmf<IEnumFilters, IBaseFilter **, HRESULT> * DSGraphContainer::iterator::Next = NULL;
  43. // DSFilter
  44. std_arity1pmf<IBaseFilter, IEnumPins **, HRESULT> * DSFilter::Fetch = NULL;
  45. std_arity0pmf<IEnumPins, HRESULT> * DSFilter::iterator::Reset = NULL;
  46. std_arity1pmf<IEnumPins, IPin **, HRESULT> * DSFilter::iterator::Next = NULL;
  47. // DSDevices
  48. std_arity1pmf<ICreateDevEnum, IEnumMoniker **, HRESULT> * DSDeviceSequence::Fetch = NULL; // no arity0 fetch actually exists. overridden with bound functor in DSDeviceSequence::GetFetch
  49. std_arity0pmf<IEnumMoniker, HRESULT> * DSDevices::iterator::Reset = NULL;
  50. std_arity1pmf<IEnumMoniker, IMoniker **, HRESULT> * DSDevices::iterator::Next = NULL;
  51. // DSFilterMapper
  52. std_arity1pmf<IFilterMapper2, IEnumMoniker **, HRESULT> * DSFilterMapperSequence::Fetch = NULL;// no arity0 fetch actually exists. overridden with bound functor in DSFilterMapperSequence::GetFetch
  53. // uses same types as DSDevices so its the same template expansion, already initialized
  54. // DSPin
  55. std_arity1pmf<IPin, IEnumMediaTypes **, HRESULT> * DSPin::Fetch = NULL;
  56. std_arity0pmf<IEnumMediaTypes, HRESULT> * DSPin::iterator::Reset = NULL;
  57. std_arity1pmf<IEnumMediaTypes, AM_MEDIA_TYPE **, HRESULT> * DSPin::iterator::Next = NULL;
  58. #endif
  59. // work around compiler bug as per above description
  60. void CtorStaticDSExtendFwdSeqPMFs(void) {
  61. // DSGraphContainer
  62. DSGraphContainer::Fetch = new std_arity1pmf<IGraphBuilder, IEnumFilters **, HRESULT>(&IGraphBuilder::EnumFilters);
  63. DSGraphContainer::iterator::Reset = new std_arity0pmf<IEnumFilters, HRESULT>(&IEnumFilters::Reset);
  64. DSGraphContainer::iterator::Next = new std_bndr_mf_1_3<std_arity3pmf<IEnumFilters, ULONG, IBaseFilter**, ULONG *, HRESULT> >(std_arity3_member(&IEnumFilters::Next), 1, &dwFetch);
  65. // DSFilter
  66. DSFilter::Fetch = new std_arity1pmf<IBaseFilter, IEnumPins **, HRESULT>(&IBaseFilter::EnumPins);
  67. DSFilter::iterator::Reset = new std_arity0pmf<IEnumPins, HRESULT>(&IEnumPins::Reset);
  68. DSFilter::iterator::Next = new std_bndr_mf_1_3<std_arity3pmf<IEnumPins, ULONG, IPin **, ULONG *, HRESULT> >(std_arity3_member(&IEnumPins::Next), 1, &dwFetch);
  69. // DSDevices
  70. // DSDeviceSequence::Fetch, no arity0 fetch actually exists. overridden with bound functor in DSDeviceSequence::GetFetch
  71. DSDevices::iterator::Reset = new std_arity0pmf<IEnumMoniker, HRESULT>(&IEnumMoniker::Reset);
  72. DSDevices::iterator::Next = new std_bndr_mf_1_3<std_arity3pmf<IEnumMoniker, ULONG, IMoniker **, ULONG *, HRESULT> >(std_arity3_member(&IEnumMoniker::Next), 1, &dwFetch);
  73. // DSFilterMapper, no arity0 fetch actually exists. overridden with bound functor in DSFilterMapperSequence::GetFetch
  74. // uses same types as DSDevices so its the same template expansion, already initialized
  75. // DSPin
  76. DSPin::Fetch = new std_arity1pmf<IPin, IEnumMediaTypes **, HRESULT>(&IPin::EnumMediaTypes);
  77. DSPin::iterator::Reset = new std_arity0pmf<IEnumMediaTypes, HRESULT>(&IEnumMediaTypes::Reset);
  78. DSPin::iterator::Next = new std_bndr_mf_1_3<std_arity3pmf<IEnumMediaTypes, DWORD, AM_MEDIA_TYPE **, DWORD *, HRESULT> >(std_arity3_member(&IEnumMediaTypes::Next), 1, &dwFetch);
  79. }
  80. // work around compiler bug as per above description
  81. void DtorStaticDSExtendFwdSeqPMFs(void) {
  82. // DSGraphContainer
  83. delete DSGraphContainer::Fetch;
  84. delete DSGraphContainer::iterator::Reset;
  85. delete DSGraphContainer::iterator::Next;
  86. // DSFilter
  87. delete DSFilter::Fetch;
  88. delete DSFilter::iterator::Reset;
  89. delete DSFilter::iterator::Next;
  90. // DSDevices
  91. // DSDeviceSequence::Fetch, no arity0 fetch actually exists. overridden with bound functor in DSDeviceSequence::GetFetch
  92. delete DSDevices::iterator::Reset;
  93. delete DSDevices::iterator::Next;
  94. // DSFilterMapper, no arity0 fetch actually exists. overridden with bound functor in DSFilterMapperSequence::GetFetch
  95. // uses same types as DSDevices so its the same template expansion, already initialized
  96. // DSPin
  97. delete DSPin::Fetch;
  98. delete DSPin::iterator::Reset;
  99. delete DSPin::iterator::Next;
  100. }
  101. ///////////////////////////////////////////////////////////////////////////////////////////////
  102. // DSGraph
  103. ///////////////////////////////////////////////////////////////////////////////////////////////
  104. HRESULT DSGraph::Connect(DSFilter &pStart, DSFilter &pStop, DSFilterList &Added, const DWORD dwFlags, PIN_DIRECTION pd)
  105. {
  106. ASSERT(*this);
  107. ASSERT(pStart.GetGraph() == *this);
  108. ASSERT(pStop.GetGraph() == *this);
  109. try {
  110. DSFilterIDList AddedIDs;
  111. int origsize = Added.size();
  112. if (ConnectFilters(pStart, pStop, AddedIDs, dwFlags, pd)) {
  113. for (DSFilterIDList::iterator i = AddedIDs.begin(); i != AddedIDs.end(); ++i) {
  114. Added.push_back((*i).first);
  115. }
  116. return NOERROR;
  117. }
  118. ASSERT(!AddedIDs.size());
  119. ASSERT(Added.size() == origsize);
  120. return E_FAIL;
  121. } catch (ComException &e) {
  122. return e;
  123. } catch (...) {
  124. return E_UNEXPECTED;
  125. }
  126. }
  127. bool DSGraph::Connect(DSFilter &pStart, DSFilterMoniker &pStop, DSFilter &pEndPointAdded, DSFilterList &IntermediatesAdded, const DWORD dwFlags, PIN_DIRECTION pd)
  128. {
  129. ASSERT(*this);
  130. ASSERT(pStart.GetGraph() == *this);
  131. pEndPointAdded = AddMoniker(pStop);
  132. if (!pEndPointAdded) {
  133. return false;
  134. }
  135. ASSERT(pEndPointAdded.GetGraph() == *this);
  136. int origsize = IntermediatesAdded.size();
  137. if (SUCCEEDED(Connect(pStart, pEndPointAdded, IntermediatesAdded, dwFlags, pd))) {
  138. return true;
  139. }
  140. RemoveFilter(pEndPointAdded);
  141. pEndPointAdded.Release();
  142. ASSERT(IntermediatesAdded.size() == origsize);
  143. return false;
  144. }
  145. #ifdef ATTEMPT_DIRECT_CONNECT
  146. // attempt to connect the given pin to some pin on the given filter
  147. bool DSGraph::ConnectPinDirect(DSPin &pPin, DSFilter &pFilter, DWORD dwFlags) {
  148. try {
  149. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectPinDirect() pPin = " << pPin << " pFilter = " << pFilter), "");
  150. TRACEINDENT();
  151. DSFilter::iterator i;
  152. for (i = pFilter.begin(); i != pFilter.end(); ++i) {
  153. if (!DSPin(*i).GetConnection()) {
  154. HRESULT hr = pPin.Connect(*i, NULL);
  155. if (SUCCEEDED(hr)) {
  156. TRACEOUTDENT();
  157. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::ConnectPinDirect() connected " << pPin.GetFilter() << " " << pPin << " to " << DSPin(*i).GetFilter() << " " << *i), "");
  158. return true;
  159. }
  160. }
  161. }
  162. TRACEOUTDENT();
  163. } catch(...) {
  164. TRACEOUTDENT();
  165. }
  166. #if 0
  167. // for perf reasons, we would like to short-circuit destinations that have no
  168. // free pins by throwing, causing a roll back to the next filter to try
  169. // however, this breaks topologies where two source pins route through intermediate filters
  170. // and into a single pin going into the destination filter.
  171. // example: this causes the analog audio pin coming off an analog tuner to fail to connect
  172. // through to the crossbar because the capture filter is already connected to video.
  173. if (!cUseablePins) {
  174. TRACELM(TRACE_DETAIL, "ConnectPinDirect() no useable pins, throwing...");
  175. THROWCOM(HRESULT_FROM_WIN32(ERROR_OUT_OF_STRUCTURES)); // short cut the case where there aren't any useable pins by any criteria
  176. }
  177. #endif
  178. TRACELM(TRACE_DETAIL, "ConnectPinDirect() failed");
  179. return false;
  180. }
  181. #endif
  182. #ifndef ATTEMPT_DIRECT_CONNECT
  183. // attempt to connect the given pin to some pin on the given filter
  184. bool DSGraph::ConnectPinByMedium(DSPin &pPin, DSFilter &pFilter, DWORD dwFlags) {
  185. int cUseablePins = 0;
  186. try {
  187. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectPinByMedium() pPin = " << pPin << " pFilter = " << pFilter), "");
  188. TRACEINDENT();
  189. DSFilter::iterator i;
  190. for (i = pFilter.begin(); i != pFilter.end(); ++i) {
  191. if (HasUnconnectedMedium(pPin, *i, cUseablePins)) {
  192. break;
  193. }
  194. }
  195. if (i != pFilter.end()) {
  196. HRESULT hr = pPin.Connect(*i, NULL);
  197. if (FAILED(hr)) {
  198. TRACEOUTDENT();
  199. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::ConnectPinByMedium() can't connect pin " << pPin << " to " << *i), " with matching medium");
  200. return false;
  201. }
  202. TRACEOUTDENT();
  203. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::ConnectPinByMedium() connected " << pPin.GetFilter() << " " << pPin << " to " << DSPin(*i).GetFilter() << " " << *i), "");
  204. return true;
  205. }
  206. TRACEOUTDENT();
  207. } catch(...) {
  208. TRACEOUTDENT();
  209. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::ConnectPinByMedium() connect pin "), " THREWUP");
  210. }
  211. #if 0
  212. // for perf reasons, we would like to short-circuit destinations that have no
  213. // free pins by throwing, causing a roll back to the next filter to try
  214. // however, this breaks topologies where two source pins route through intermediate filters
  215. // and into a single pin going into the destination filter.
  216. // example: this causes the analog audio pin coming off an analog tuner to fail to connect
  217. // through to the crossbar because the capture filter is already connected to video.
  218. if (!cUseablePins) {
  219. TRACELM(TRACE_DETAIL, "ConnectPinByMedium() no useable pins, throwing...");
  220. THROWCOM(HRESULT_FROM_WIN32(ERROR_OUT_OF_STRUCTURES)); // short cut the case where there aren't any useable pins by any criteria
  221. }
  222. #endif
  223. TRACELM(TRACE_DETAIL, "ConnectPinByMedium() failed");
  224. return false;
  225. }
  226. #endif
  227. // attempt to connect the given pin to the given filter by hunting for an indirection through
  228. // another filter already in the graph
  229. // then attempt to connect the new filter to the original destination
  230. bool DSGraph::FindPinByMedium(DSPin &pPin1, DSFilter &pFDest, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags) {
  231. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::FindPinByMedium() pPin1 = " << pPin1 << " pFDest = " << pFDest), "");
  232. KSMediumList ml;
  233. HRESULT hr = pPin1.GetMediums(ml);
  234. if (FAILED(hr) || !ml.size()) {
  235. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::FindPinByMedium() " << pPin1 << " has no mediums"), "");
  236. return false;
  237. }
  238. try {
  239. TRACEINDENT();
  240. // possibly in the future we should find all of the possible choices and
  241. // use the shortest available path. but for now, we're just going to
  242. // find the first one that exists
  243. // try all the direct connections
  244. for (DSGraphContainer::iterator i = begin(); i != end(); ++i) {
  245. #ifdef ATTEMPT_DIRECT_CONNECT
  246. if (IsConnectable(pPin1, DSFilter(*i), pFDest, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinDirect))) {
  247. #else
  248. if (IsConnectable(pPin1, DSFilter(*i), pFDest, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinByMedium))) {
  249. #endif
  250. TRACEOUTDENT();
  251. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMedium() succeeded");
  252. return true;
  253. }
  254. }
  255. TRACEOUTDENT();
  256. } catch(...) {
  257. TRACEOUTDENT();
  258. }
  259. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMedium() can't connect pin to anything in graph");
  260. return false;
  261. }
  262. // we have already established that we can't connect directly or via other filters
  263. // already in the graph so go hunt for a new filter to load
  264. // if we fail we must leave the graph in its initial state
  265. bool DSGraph::LoadPinByMedium(KSPinMedium &medium, DSPin &pPin1, DSFilter &pFilter1, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags) {
  266. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMedium() pPin1 = " << pPin1 << " pFilter1 = " << pFilter1), "");
  267. if (medium == NULL_MEDIUM || medium == HOST_MEMORY_MEDIUM) {
  268. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByMedium() NULL Medium, don't bother");
  269. // don't build an enumerator for a null medium or we will search through every
  270. // single filter on the system that doesn't have mediums
  271. return false;
  272. }
  273. try {
  274. TRACEINDENT();
  275. TRACELSM(TRACE_PAINT, (dbgDump << "medium = " << medium), "");
  276. PIN_DIRECTION pd;
  277. HRESULT hr = pPin1->QueryDirection(&pd);
  278. if (FAILED(hr)) {
  279. TRACEOUTDENT();
  280. TRACELM(TRACE_ERROR, "DSGraph::LoadPinByMedium() can't query direction");
  281. THROWCOM(E_UNEXPECTED);
  282. }
  283. bool fInReq = false, fOutReq = false;
  284. DSREGPINMEDIUM *pInMed = NULL, *pOutMed = NULL;
  285. switch (pd) {
  286. case PINDIR_INPUT: // hunting through graph from right to left
  287. #ifdef FILTERDATA
  288. fOutReq = true;
  289. pOutMed = reinterpret_cast<DSREGPINMEDIUM *>(&medium);
  290. #else
  291. // NOTE: because of mediums get registered from the .inf with an
  292. // incomplete registry blob, filtermapper thinks that any pin with a
  293. // medium is an input pin and we use the low flag bit in the second
  294. // medium dword to solve this problem. == 1 for input == 0 for output
  295. fInReq = true;
  296. pInMed = reinterpret_cast<DSREGPINMEDIUM *>(&medium);
  297. medium.Flags &= ~(KSMEDIUM_INPUTFLAG);
  298. #endif
  299. break;
  300. case PINDIR_OUTPUT: // hunting through graph from left to right
  301. fInReq = true;
  302. pInMed = reinterpret_cast<DSREGPINMEDIUM *>(&medium);
  303. #ifndef FILTERDATA
  304. medium.Flags |= KSMEDIUM_INPUTFLAG;
  305. #endif
  306. break;
  307. }
  308. if (pInMed) {
  309. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMedium() fInReq = " << fInReq << " pInMed = " << pInMed << " " << (*pInMed)), "");
  310. } else {
  311. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMedium() fInReq = " << fInReq << " pInMed = " << pInMed << " (NULL)"), "");
  312. }
  313. if (pOutMed) {
  314. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMedium() fOutReq = " << fOutReq << " pOutMed = " << pOutMed << " " << (*pOutMed)), "");
  315. } else {
  316. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMedium() fOutReq = " << fOutReq << " pOutMed = " << pOutMed << " (Null)"), "");
  317. }
  318. // NOTE: since we're using mediums which are hw specific we include filters w/
  319. // MERIT_DO_NOT_USE since this is the default merit and most HW device filters
  320. // don't specify a merit.
  321. DSFilterMapper fmr(PQFilterMapper(*this),
  322. 0,
  323. true, // no wildcards
  324. MERIT_DO_NOT_USE, // default merit for hw filters
  325. fInReq, // input required
  326. 0,
  327. NULL,
  328. pInMed, // input medium
  329. NULL, // input pin cat
  330. false, // input rendered?
  331. fOutReq, // output required
  332. 0,
  333. NULL,
  334. pOutMed, // output medium
  335. NULL // output pin cat
  336. );
  337. if (fmr) {
  338. // try all the direct connections
  339. for (DSFilterMapper::iterator i = fmr.begin(); i != fmr.end(); ++i) {
  340. #ifdef ATTEMPT_DIRECT_CONNECT
  341. if (IsLoadable(pPin1, DSFilterMoniker(*i), pFilter1, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinDirect))) {
  342. #else
  343. if (IsLoadable(pPin1, DSFilterMoniker(*i), pFilter1, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinByMedium))) {
  344. #endif
  345. TRACEOUTDENT();
  346. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByMedium() succeeded");
  347. return true;
  348. }
  349. }
  350. }
  351. TRACEOUTDENT();
  352. } catch(...) {
  353. TRACEOUTDENT();
  354. }
  355. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByMedium() failed");
  356. return false;
  357. }
  358. bool DSGraph::LoadPinByAnyMedium(DSPin &pPin, DSFilter &pRight, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags) {
  359. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByAnyMedium()");
  360. try {
  361. KSMediumList ml;
  362. HRESULT hr = pPin.GetMediums(ml);
  363. if (FAILED(hr) || !ml.size()) {
  364. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByAnyMedium() " << pPin << " has no mediums"), "");
  365. return false;
  366. }
  367. for (KSMediumList::iterator i = ml.begin(); i != ml.end(); ++i) {
  368. if (LoadPinByMedium(KSPinMedium(*i), pPin, pRight, IntermediatesAdded, dwFlags)) {
  369. return true;
  370. }
  371. }
  372. } catch(ComException& h) {
  373. if (h == E_UNEXPECTED) {
  374. try {
  375. TRACELM(TRACE_DEBUG, "DSGraph::LoadPinByAnyMedium() rethrowing E_UNEXPECTED");
  376. } catch(...) {
  377. }
  378. throw;
  379. }
  380. try {
  381. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::LoadPinByAnyMedium() suppressing HRESULT = " << hexdump(h)), "");
  382. } catch(...) {
  383. }
  384. } catch(...) {
  385. }
  386. return false;
  387. }
  388. #ifndef ATTEMPT_DIRECT_CONNECT
  389. // attempt to connect these two filters. if we fail we must remove
  390. // any intermediate filters that we may have added and leave the graph in the
  391. // state we started with.
  392. bool DSGraph::ConnectPinByMediaType(DSPin &pPin1, DSFilter &pFilter1, DWORD dwFlags) {
  393. ASSERT(pPin1.GetGraph() == *this);
  394. ASSERT(pFilter1.GetGraph() == *this);
  395. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectPinByMediaType(DSPin, DSFilter) pPin1 = " << pPin1 << " pFilter1 = " << pFilter1), "");
  396. try {
  397. TRACEINDENT();
  398. // try media types
  399. DSFilter::iterator i;
  400. for (i = pFilter1.begin(); i != pFilter1.end(); ++i) {
  401. if (HasUnconnectedMediaType(pPin1, *i, dwFlags)) {
  402. break;
  403. }
  404. }
  405. if (i != pFilter1.end()) {
  406. ASSERT(*this);
  407. ASSERT(pPin1.GetGraph() == *this);
  408. ASSERT((*i).GetGraph() == *this);
  409. HRESULT hr = pPin1.Connect(*i, NULL);
  410. if (FAILED(hr)) {
  411. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::ConnectPinByMediaType(DSPin, DSFilter) can't connect pin " << pPin1 << " to " << *i << " hr = " << hexdump(hr)), " with matching media type.");
  412. #ifdef DEBUG
  413. if (dwTraceLevel >= TRACE_DETAIL) {
  414. DumpHdr(dbgDump) << "pin1 " << pPin1.GetFilter() << " " << pPin1 << std::endl;
  415. DumpHdr(dbgDump) << "pin2 " << (*i).GetFilter() << " " << *i << std::endl;
  416. DumpMediaTypes(pPin1, *i);
  417. }
  418. #endif
  419. if (!(dwFlags & IGNORE_MEDIATYPE_ERRORS)) {
  420. THROWCOM(HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH));
  421. } else {
  422. return false;
  423. }
  424. }
  425. TRACEOUTDENT();
  426. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::ConnectPinByMediaType(DSPin, DSFilter) connected " << pPin1.GetFilter() << " " << pPin1 << " to " << DSPin(*i).GetFilter() << " " << *i), "");
  427. return true;
  428. }
  429. TRACEOUTDENT();
  430. } catch(ComException& h) {
  431. TRACEOUTDENT();
  432. if (h == E_UNEXPECTED || h == HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)) {
  433. try {
  434. TRACELM(TRACE_DEBUG, "DSGraph::ConnectPinByMediaType() rethrowing");
  435. } catch(...) {
  436. }
  437. throw;
  438. }
  439. try {
  440. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::ConnectPinByMediaType() suppressing HRESULT = " << hexdump(h)), "");
  441. } catch(...) {
  442. }
  443. } catch(...) {
  444. TRACEOUTDENT();
  445. }
  446. TRACELM(TRACE_DEBUG, "DSGraph::ConnectPinByMediaType(DSPin, DSFilter) failed");
  447. return false;
  448. }
  449. #endif
  450. bool DSGraph::FindPinByMediaType(DSPin &pPinLeft, DSFilter &pRight, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags) {
  451. ASSERT(pPinLeft.GetGraph() == *this);
  452. ASSERT(pRight.GetGraph() == *this);
  453. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::FindPinByMediaType() pPinLeft = " << pPinLeft << " filter = " << pRight), "");
  454. // possibly in the future we should find all of the possible choices and
  455. // use the shortest available path. but for now, we're just going to
  456. // find the first one that exists
  457. try {
  458. TRACEINDENT();
  459. // NOTE: IFilterGraph::ConnectDirect() bumps the graph version number which invalidates
  460. // all the enumerators. thus we'll run through and make a list of all the filters in the
  461. // graph and then check them
  462. DSFilterList l;
  463. for (DSGraphContainer::iterator i = begin(); i != end(); ++i) {
  464. l.push_back(*i);
  465. }
  466. for (DSFilterList::iterator li = l.begin(); li != l.end(); ++li) {
  467. #ifdef ATTEMPT_DIRECT_CONNECT
  468. if (IsConnectable(pPinLeft, DSFilter(*li), pRight, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinDirect))) {
  469. #else
  470. if (IsConnectable(pPinLeft, DSFilter(*li), pRight, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinByMediaType))) {
  471. #endif
  472. TRACEOUTDENT();
  473. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMediaType() succeeded");
  474. return true;
  475. }
  476. }
  477. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMediaType() enumeration exhausted");
  478. TRACEOUTDENT();
  479. } catch(ComException& h) {
  480. TRACEOUTDENT();
  481. if (h == E_UNEXPECTED) {
  482. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMediaType() rethrowing E_UNEXPECTED");
  483. throw;
  484. }
  485. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::FindPinByMediaType() suppressing HRESULT = " << hexdump(h)), "");
  486. } catch(...) {
  487. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMediaType() catch ...");
  488. TRACEOUTDENT();
  489. }
  490. TRACELM(TRACE_DETAIL, "DSGraph::FindPinByMediaType() failed");
  491. return false;
  492. }
  493. bool DSGraph::LoadPinByAnyMediaType(DSPin &pPin, DSFilter &pRight, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags) {
  494. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByAnyMediaType() pPin = " << pPin.GetName() << " dwFlags = " << hexdump(dwFlags)), "");
  495. ASSERT(pPin.GetGraph() == *this);
  496. ASSERT(pRight.GetGraph() == *this);
  497. #ifdef DEBUG
  498. BEGIN_TRACEL(TRACE_DETAIL)
  499. if (pPin.begin() == pPin.end()) {
  500. dbgDump << "DSGraph::LoadPinByAnyMediaType() pin has no media types\r\n";
  501. dbgDump.flush();
  502. }
  503. END_TRACEL
  504. #endif
  505. try {
  506. DWORD dwMerit = MERIT_NORMAL;
  507. if (dwFlags & ATTEMPT_MERIT_UNLIKELY) {
  508. dwMerit = MERIT_UNLIKELY;
  509. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByAnyMediaType() MERIT_UNLIKELY");
  510. } else if (dwFlags & ATTEMPT_MERIT_DO_NOT_USE) {
  511. dwMerit = MERIT_DO_NOT_USE;
  512. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByAnyMediaType() MERIT_DO_NOT_USE");
  513. }
  514. return LoadPinByMediaType(pPin, pRight, IntermediatesAdded, dwFlags, dwMerit);
  515. } catch(ComException& h) {
  516. if ((h == E_UNEXPECTED) ||
  517. (h == HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)) ||
  518. (h == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
  519. ) {
  520. try {
  521. TRACELM(TRACE_DEBUG, "DSGraph::LoadPinByAnyMediaType() rethrowing");
  522. } catch(...) {
  523. }
  524. throw;
  525. }
  526. try {
  527. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::LoadPinByAnyMediaType() suppressing HRESULT = " << hexdump(h)), "");
  528. } catch(...) {
  529. }
  530. } catch(...) {
  531. }
  532. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByAnyMediaType() failed");
  533. return false;
  534. }
  535. // we are trying to connect Pin1 to the Destination Filter. we have already
  536. // established that we cannot connect them directly.
  537. // Mapper is a moniker for a filter provided by the filtermapper enumerator that we're
  538. // going to attempt to use as an intermediate filter
  539. bool DSGraph::IsConnectable(DSPin &pPin1, DSFilter &pNew, DSFilter &pFDestination, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags, ConnectPred_t ConnPred) {
  540. ASSERT(pPin1 != NULL);
  541. ASSERT(pPin1.GetGraph() == *this);
  542. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsConnectable() pPin1 = " << pPin1 << " pNew = " << pNew << " pFDestination = " << pFDestination), "");
  543. try {
  544. PIN_INFO pinfo;
  545. HRESULT hr = pPin1->QueryPinInfo(&pinfo);
  546. if (FAILED(hr)) {
  547. THROWCOM(E_UNEXPECTED);
  548. }
  549. DSFilter Pin1Filter;
  550. Pin1Filter.p = pinfo.pFilter; // transfer refcount ownership
  551. if (pNew && pNew != pFDestination && pNew != Pin1Filter) {
  552. bool f1 = (this->*ConnPred)(pPin1, pNew, dwFlags);
  553. if (f1) {
  554. TRACELM(TRACE_DETAIL, "DSGraph::IsConnectable() connpred == true");
  555. PIN_DIRECTION direction;
  556. hr = pPin1->QueryDirection(&direction);
  557. if (FAILED(hr)) {
  558. TRACELM(TRACE_ERROR, "DSGraph::IsConnectable() can't query direction");
  559. THROWCOM(E_UNEXPECTED);
  560. }
  561. if (ConnectFilters(pNew, pFDestination, IntermediatesAdded, dwFlags, direction)) {
  562. TRACELM(TRACE_DETAIL, "DSGraph::IsConnectable() succeeded");
  563. return true;
  564. }
  565. }
  566. }
  567. } catch(ComException& h) {
  568. if (h == E_UNEXPECTED) {
  569. try {
  570. TRACELM(TRACE_DEBUG, "DSGraph::IsConnectable() rethrowing E_UNEXPECTED");
  571. pPin1.Disconnect();
  572. } catch(...) {
  573. }
  574. throw;
  575. }
  576. try {
  577. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsConnectable() suppressing HRESULT = " << hexdump(h)), "");
  578. } catch(...) {
  579. }
  580. } catch(...) {
  581. }
  582. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsConnectable() disconnecting " << pPin1), "");
  583. pPin1.Disconnect();
  584. return false;
  585. }
  586. // we are trying to connect Pin1 to the Destination Filter. we have already
  587. // established that we cannot connect them directly.
  588. // Mapper is a moniker for a filter provided by the filtermapper enumerator that we're
  589. // going to attempt to use as an intermediate filter
  590. bool DSGraph::IsLoadable(DSPin &pPin1, DSFilterMoniker &Mapper, DSFilter &Destination, DSFilterIDList &IntermediatesAdded, DWORD dwFlags, ConnectPred_t ConnPred) {
  591. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsLoadable() pPin1 = " << pPin1 << " " << pPin1.GetFilter() << " Destination = " << Destination), "");
  592. ASSERT(pPin1.GetGraph() == *this);
  593. DSFilter pNew;
  594. try {
  595. DSFilterIDList::iterator i = IntermediatesAdded.size() ? (IntermediatesAdded.end() - 1) : IntermediatesAdded.end();
  596. if (i != IntermediatesAdded.end()) {
  597. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsLoadable() checking duplicate moniker last = " << (*i).second << " new = " << Mapper.DisplayName()), "");
  598. } else {
  599. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsLoadable() first moniker can't be dup(no check) new = " << Mapper.DisplayName()), "");
  600. }
  601. // undone: if the chains get longer we should use a map for this. this may explain why perf
  602. // collapses as soon as we end up over on the audio side of things
  603. int occurrences = 0;
  604. CString newmkrname = Mapper.DisplayName();
  605. for (i = IntermediatesAdded.begin(); i != IntermediatesAdded.end(); ++i) {
  606. if ((!(*i).second.IsEmpty()) &&
  607. (newmkrname == (*i).second)) {
  608. ++occurrences;
  609. }
  610. }
  611. if (occurrences > MAX_OCCURRENCE_COUNT) {
  612. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::IsLoadable() max occurrence count exceeded for mkr = " << newmkrname), "");
  613. return false;
  614. }
  615. pNew = AddMoniker(Mapper);
  616. IntermediatesAdded.push_back(DSFilterID(pNew, Mapper.DisplayName()));
  617. // ???? implement flag
  618. if (pNew) {
  619. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsLoadable() added moniker pNew = " << pNew), "");
  620. bool f1 = (this->*ConnPred)(pPin1, pNew, dwFlags);
  621. if (f1) {
  622. TRACELM(TRACE_DETAIL, "DSGraph::IsLoadable() connpred succeeded");
  623. PIN_DIRECTION direction;
  624. HRESULT hr = pPin1->QueryDirection(&direction);
  625. if (FAILED(hr)) {
  626. TRACELM(TRACE_ERROR, "DSGraph::IsLoadable() can't query direction");
  627. THROWCOM(E_UNEXPECTED);
  628. }
  629. if (!pNew.PinCount(direction)) {
  630. if (!(dwFlags & DONT_TERMINATE_ON_RENDERER)) {
  631. TRACELM(TRACE_DETAIL, "DSGraph::IsLoadable() throwing ERROR_NO_MORE_ITEMS");
  632. THROWCOM(HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
  633. }
  634. }
  635. if (ConnectFilters(pNew, Destination, IntermediatesAdded, dwFlags, direction)) {
  636. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::IsLoadable() succeeded. pPin1 = " << pPin1 << " pNew = " << pNew << " Destination = " << Destination), "");
  637. return true;
  638. }
  639. }
  640. }
  641. } catch(ComException& h) {
  642. if ((h == E_UNEXPECTED) ||
  643. (h == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))) {
  644. try {
  645. TRACELM(TRACE_DEBUG, "DSGraph::IsLoadable() rethrowing");
  646. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsLoadable() disconnecting " << pPin1), "");
  647. pPin1.Disconnect();
  648. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsLoadable() removing " << pNew), "");
  649. IntermediatesAdded.pop_back();
  650. RemoveFilter(pNew);
  651. } catch(...) {
  652. }
  653. throw;
  654. }
  655. try {
  656. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsLoadable() suppressing HRESULT = " << hexdump(h)), "");
  657. } catch(...) {
  658. }
  659. } catch(...) {
  660. }
  661. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsLoadable() disconnecting " << pPin1), "");
  662. pPin1.Disconnect();
  663. IntermediatesAdded.pop_back();
  664. if (pNew) {
  665. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::IsLoadable() removing " << pNew), "");
  666. RemoveFilter(pNew);
  667. }
  668. return false;
  669. }
  670. bool DSGraph::ConnectPin(DSPin &pPin1, DSFilter &pFilter1, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags, PIN_DIRECTION pin1dir) {
  671. // NOTE: this is where we enforce the desired directional assymetry. from now on through the call tree
  672. // we can assume that pin1 is already the desired directional type. and we only have to check
  673. // pin2 at the end in hasunconnectedxxxx()
  674. // this ensures that all of our connection paths are unidirectional through the graph. in other words,
  675. // make sure that we don't go downstream then back upstream or vice versa.
  676. // this allows all of our connection routines to be useable from either direction
  677. // since there are times when we have an input side starting point and other times the opposite
  678. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectPin() pin1 = " << pPin1 << " " << pPin1.GetFilter() << " to " << pFilter1), "");
  679. TRACEINDENT();
  680. PIN_DIRECTION pd;
  681. HRESULT hr = pPin1->QueryDirection(&pd);
  682. if (pd != pin1dir) {
  683. TRACEOUTDENT();
  684. TRACELM(TRACE_PAINT, "DSGraph::ConnectPin() wrong dir");
  685. return false;
  686. }
  687. if (!(dwFlags & RENDER_ALL_PINS) && !pPin1.IsRenderable()) {
  688. TRACEOUTDENT();
  689. TRACELM(TRACE_PAINT, "DSGraph::ConnectPin() non-renderable");
  690. return false;
  691. }
  692. // make sure we're not trying to connect a filter to itself
  693. PIN_INFO pinfo;
  694. DSFilter PinFilter;
  695. hr = pPin1->QueryPinInfo(&pinfo);
  696. if (FAILED(hr)) {
  697. TRACEOUTDENT();
  698. TRACELM(TRACE_ERROR, "DSGraph::ConnectPin() can't get pin info");
  699. THROWCOM(E_UNEXPECTED);
  700. }
  701. PinFilter.p = pinfo.pFilter; // transfer refcount ownership
  702. if (PinFilter == pFilter1) {
  703. TRACEOUTDENT();
  704. TRACELM(TRACE_PAINT, "DSGraph::ConnectPin() can't connect filter to itself");
  705. return false;
  706. }
  707. DSPin pConn = pPin1.GetConnection();
  708. if (!!pConn) {
  709. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectPin() pin1 = " << pPin1 << " connected, tracing through to next filter = " << pConn.GetFilter()), "");
  710. // a connected output pin should be traced through the next filter
  711. DSFilter pNext = pConn.GetFilter();
  712. if (!pNext) {
  713. TRACEOUTDENT();
  714. TRACELM(TRACE_ERROR, "DSGraph::ConnectPin() pNext has no filter");
  715. THROWCOM(E_UNEXPECTED);
  716. }
  717. if (pNext != pFilter1) {
  718. bool rc = ConnectFilters(pNext, pFilter1, IntermediatesAdded, dwFlags, pin1dir);
  719. TRACEOUTDENT();
  720. return rc;
  721. } else {
  722. TRACEOUTDENT();
  723. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() pNext == pFilter1");
  724. return true;
  725. }
  726. }
  727. #if 0
  728. // for perf reasons, we would like to short-circuit destinations that have no
  729. // free pins by returning, causing a roll back to the next filter to try
  730. // however, this breaks topologies where two source pins route through intermediate filters
  731. // and into a single pin going into the destination filter.
  732. // example: this causes the analog audio pin coming off an analog tuner to fail to connect
  733. // through to the crossbar because the capture filter is already connected to video.
  734. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() pin free");
  735. PIN_DIRECTION pd2;
  736. pd2 = OppositeDirection(pd);
  737. if (!pFilter1.HasFreePins(pd2)) {
  738. TRACEOUTDENT();
  739. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() filter has no free pins");
  740. return false;
  741. }
  742. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() filter has free pins");
  743. #endif
  744. try {
  745. #ifdef ATTEMPT_DIRECT_CONNECT
  746. if (ConnectPinDirect(pPin1, pFilter1) || // can these connect direct
  747. #else
  748. if (ConnectPinByMedium(pPin1, pFilter1, dwFlags) || // can these connect direct
  749. #endif
  750. FindPinByMedium(pPin1, pFilter1, IntermediatesAdded, dwFlags) || // any paths in graph
  751. (!(dwFlags & DO_NOT_LOAD) && LoadPinByAnyMedium(pPin1, pFilter1, IntermediatesAdded, dwFlags)) || // any filters in system
  752. #ifndef ATTEMPT_DIRECT_CONNECT
  753. ConnectPinByMediaType(pPin1, pFilter1, dwFlags) || // can these connect direct
  754. #endif
  755. FindPinByMediaType(pPin1, pFilter1, IntermediatesAdded, dwFlags) ||
  756. (!(dwFlags & DO_NOT_LOAD) && LoadPinByAnyMediaType(pPin1, pFilter1, IntermediatesAdded, dwFlags))) {
  757. TRACEOUTDENT();
  758. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() succeeded");
  759. return true;
  760. }
  761. TRACEOUTDENT(); // to avoid outdenting too far in a catch case
  762. } catch (ComException &h) {
  763. TRACEOUTDENT();
  764. if (h == E_UNEXPECTED) {
  765. try {
  766. TRACELM(TRACE_DEBUG, "DSGraph::ConnectPin() rethrowing E_UNEXPECTED");
  767. } catch(...) {
  768. }
  769. throw;
  770. }
  771. try {
  772. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::ConnectPin() suppressing HRESULT = " << hexdump(h)), "");
  773. } catch(...) {
  774. }
  775. } catch (...) {
  776. TRACEOUTDENT();
  777. }
  778. //TRACEOUTDENT();
  779. TRACELM(TRACE_DETAIL, "DSGraph::ConnectPin() failed");
  780. return false;
  781. }
  782. // attempt to disconnect this pin
  783. bool DSGraph::DisconnectPin(DSPin &pPin, const bool fRecurseInputs, const bool fRecurseOutputs) {
  784. TRACELM(TRACE_DETAIL, "DSGraph::DisconnectPin()");
  785. PIN_DIRECTION pd;
  786. HRESULT hr = pPin->QueryDirection(&pd);
  787. if (FAILED(hr)) {
  788. TRACELM(TRACE_ERROR, "DSGraph::DisconnectPin() can't get direction");
  789. THROWCOM(E_UNEXPECTED);
  790. }
  791. DSPin pConnection = pPin.GetConnection();
  792. if (!pConnection) {
  793. return false;
  794. }
  795. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::DisconnectPin() disconnecting " << pPin << " from " << pConnection), "");
  796. pPin.Disconnect();
  797. DSFilter pNext = pConnection.GetFilter();
  798. if (!pNext) {
  799. TRACELM(TRACE_ERROR, "DSGraph::DisconnectPin() pConnection has no filter");
  800. THROWCOM(E_UNEXPECTED);
  801. }
  802. switch (pd) {
  803. case PINDIR_INPUT:
  804. if (fRecurseInputs) {
  805. #if 0
  806. std::for_each(pNext.begin(),
  807. pNext.end(),
  808. bind_obj_2_3(*this,
  809. arity3_member(&DSGraph::DisconnectPin),
  810. fRecurseInputs,
  811. false)); // we moving inputward, don't backtrack
  812. #endif
  813. for (DSFilter::iterator i = pNext.begin(); i != pNext.end(); ++i) {
  814. DisconnectPin(*i, fRecurseInputs, false);
  815. }
  816. }
  817. break;
  818. case PINDIR_OUTPUT:
  819. if (fRecurseOutputs) {
  820. #if 0
  821. std::for_each(pNext.begin(),
  822. pNext.end(),
  823. bind_obj_2_3(*this,
  824. arity3_member(&DSGraph::DisconnectPin),
  825. false,
  826. fRecurseOutputs));
  827. #endif
  828. for (DSFilter::iterator i = pNext.begin(); i != pNext.end(); ++i) {
  829. DisconnectPin(*i, false, fRecurseOutputs);
  830. }
  831. }
  832. break;
  833. }
  834. TRACELM(TRACE_DETAIL, "DSGraph::DisconnectPin() succeeded");
  835. return true;
  836. }
  837. // attempt to connect this from the graph
  838. bool DSGraph::DisconnectFilter(DSFilter &pFilter, const bool fRecurseInputs, const bool fRecurseOutputs) {
  839. if (!pFilter) {
  840. TRACELM(TRACE_ERROR, "DSGraph::DisconnectFilter() can't disconnect NULL filter");
  841. return FALSE;
  842. }
  843. TRACELM(TRACE_DETAIL, "DSGraph::DisconnectFilter()");
  844. for (DSFilter::iterator i = pFilter.begin(); i != pFilter.end(); ++i) {
  845. DisconnectPin(*i, fRecurseInputs, fRecurseOutputs);
  846. }
  847. return true;
  848. }
  849. bool DSGraph::RemoveFilter(DSFilter &pFilter) {
  850. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::RemoveFilter() removing " << pFilter), "");
  851. if (!pFilter) return false;
  852. DisconnectFilter(pFilter, false, false);
  853. HRESULT hr = (*this)->RemoveFilter(pFilter);
  854. if (FAILED(hr)) {
  855. TRACELM(TRACE_ERROR, "DSGraph::RemoveFilter() can't remove filter");
  856. return false;
  857. }
  858. TRACELM(TRACE_DETAIL, "DSGraph::RemoveFilter() complete");
  859. return true;
  860. }
  861. // pin matches medium
  862. // requires an exact match, won't treat GUID_NULL as wildcard and treats 'host memory' as unmatchable
  863. bool DSGraph::HasMedium(const KSPinMedium &Medium1, const DSPin &pPin2) const {
  864. DSPin junk(pPin2);
  865. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasMedium() medium1 = " << Medium1 << " pPin2 = " << junk), "");
  866. if (Medium1 == NULL_MEDIUM || Medium1 == HOST_MEMORY_MEDIUM) {
  867. TRACELM(TRACE_DETAIL, "DSGraph::HasMedium() medium1 == NULL");
  868. return false;
  869. }
  870. KSMediumList ml;
  871. HRESULT hr = pPin2.GetMediums(ml);
  872. if (FAILED(hr) || !ml.size()) {
  873. return false;
  874. }
  875. #if 0
  876. KSMediumList::iterator i = std::find_if(ml.begin(),
  877. ml.end(),
  878. std::bind2nd(std::equal_to<KSPinMedium>(), Medium1));
  879. if (i != ml.end()) {
  880. TRACELM(TRACE_DETAIL, "DSGraph::HasMedium() succeeded");
  881. return true;
  882. }
  883. #endif
  884. KSMediumList::iterator i;
  885. for (i = ml.begin(); i != ml.end(); ++i) {
  886. if (*i == Medium1) {
  887. TRACELM(TRACE_DETAIL, "DSGraph::HasMedium() succeeded");
  888. return true;
  889. }
  890. }
  891. TRACELM(TRACE_DETAIL, "DSGraph::HasMedium() no match");
  892. return false;
  893. }
  894. bool DSGraph::HasMediaType(const DSMediaType &LeftMedia, const DSPin &pPinRight) const {
  895. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasMediaType() LeftMedia = " << LeftMedia << " LeftMedia.p " << LeftMedia.p << " pPinRight = " << pPinRight), "");
  896. if (pPinRight.IsKsProxied()) {
  897. #if 0
  898. DSPin::iterator i = std::find_if(pPinRight.begin(),
  899. pPinRight.end(),
  900. std::bind2nd(std::equal_to<DSMediaType>(),
  901. LeftMedia) );
  902. if (i != pPinRight.end()) {
  903. TRACELM(TRACE_DETAIL, "DSGraph::HasMediaType() succeeded");
  904. return true;
  905. }
  906. #endif
  907. DSPin::iterator i;
  908. for (i = pPinRight.begin(); i != pPinRight.end(); ++i) {
  909. // NOTE: DSMediaType operator== enables wildcard matches
  910. if (*i == LeftMedia) {
  911. TRACELM(TRACE_DETAIL, "DSGraph::HasMediaType() succeeded");
  912. return true;
  913. }
  914. }
  915. } else {
  916. HRESULT hr = pPinRight->QueryAccept(LeftMedia);
  917. if (SUCCEEDED(hr) && hr != S_FALSE) {
  918. TRACELM(TRACE_DETAIL, "DSGraph::HasMediaType() succeeded");
  919. return true;
  920. }
  921. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasMediaType() query accept refused hr = " << hexdump(hr)), "");
  922. }
  923. return false;
  924. }
  925. #ifndef ATTEMPT_DIRECT_CONNECT
  926. // pin is unconnected, opposite direction, and has at least 1 matching medium
  927. // requires an exact match, won't treat GUID_NULL as wildcard
  928. bool DSGraph::HasUnconnectedMedium(const DSPin &pPin1, const DSPin &pPin2, int& cUseable) const {
  929. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasUnnconnectedMedium() pin1 = " << pPin1 << " pin2 = " << pPin2), "");
  930. PIN_DIRECTION pd1, pd2;
  931. HRESULT hr = pPin1->QueryDirection(&pd1);
  932. if (FAILED(hr)) {
  933. TRACELM(TRACE_ERROR, "DSGraph::HasUnconnectedMedium() cant query pPin1 direction");
  934. return false;
  935. }
  936. hr = pPin2->QueryDirection(&pd2);
  937. if (FAILED(hr)) {
  938. TRACELM(TRACE_ERROR, "DSGraph::HasUnconnectedMedium() cant query pPin2 direction");
  939. return false;
  940. }
  941. if (pd1 == pd2) {
  942. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMedium() can't connect two pins w/ same direction");
  943. return false; // can't connect two of same type pins
  944. }
  945. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMedium() checking connection status");
  946. DSPin pConn = pPin2.GetConnection();
  947. if (!!pConn) {
  948. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasUnconnectedMedium() pPin2 = " << pPin2 << " already connected"), "");
  949. return false;
  950. }
  951. ++cUseable;
  952. KSMediumList ml;
  953. hr = pPin1.GetMediums(ml);
  954. if (FAILED(hr) || !ml.size()) {
  955. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMedium() pin has no mediums");
  956. return false;
  957. }
  958. KSMediumList::iterator i;
  959. for (i = ml.begin(); i != ml.end(); ++i) {
  960. if (HasMedium(*i, pPin2)) {
  961. break;
  962. }
  963. }
  964. if (i != ml.end()) {
  965. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMedium() succeeded");
  966. return true;
  967. }
  968. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMedium() pPin2 has no matching medium");
  969. return false;
  970. }
  971. // pin is unconnected, opposite direction, and there is at least 1 matching media type
  972. bool DSGraph::HasUnconnectedMediaType(const DSPin &pPin1, const DSPin &pPin2, DWORD dwFlags) const {
  973. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasUnnconnectedMediaType() pPin1 = " << pPin1 << " pPin2 = " << pPin2), "");
  974. if (pPin1.GetDirection() == pPin2.GetDirection()) {
  975. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMediaType() cant connect 2 pins w/ same direction");
  976. return false; // can't connect two of same type pins
  977. }
  978. DSPin pConn = pPin2.GetConnection();
  979. if (!!pConn) {
  980. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::HasUnconnectedMediaType() pPin2 connected to " << pConn), "");
  981. return false;
  982. }
  983. TRACELM(TRACE_DETAIL, "DSGraph::HasUnnconnectedMediaType() finding");
  984. // pin right isn't connected to anything so hunt for a
  985. // compatible media type
  986. for (DSPin::iterator i = pPin1.begin(); i != pPin1.end(); ++i) {
  987. if (HasMediaType(*i, pPin2)) {
  988. TRACELM(TRACE_DETAIL, "DSGraph::HasUnnconnectedMediaType() succeeded forward");
  989. return true;
  990. }
  991. }
  992. if (dwFlags & BIDIRECTIONAL_MEDIATYPE_MATCHING) {
  993. for (DSPin::iterator i = pPin2.begin(); i != pPin2.end(); ++i) {
  994. if (HasMediaType(*i, pPin1)) {
  995. TRACELM(TRACE_DETAIL, "DSGraph::HasUnnconnectedMediaType() succeeded backward(bidi)");
  996. return true;
  997. }
  998. }
  999. }
  1000. TRACELM(TRACE_DETAIL, "DSGraph::HasUnconnectedMediaType() no matching media types");
  1001. return false;
  1002. }
  1003. #endif
  1004. // we are checking to see if pPin1 is connected(possibly indirectly) to pFDestionation by traveling in destdir direction through
  1005. // the graph
  1006. bool DSGraph::IsPinConnected(const DSPin &pPin1, const DSFilter &pFDestination, DSFilterIDList &IntermediatesAdded, PIN_DIRECTION destdir) const {
  1007. PIN_DIRECTION direction;
  1008. HRESULT hr = pPin1->QueryDirection(&direction);
  1009. if (FAILED(hr)) {
  1010. TRACELM(TRACE_ERROR, "DSGraph::IsPinConnected() can't query direction");
  1011. THROWCOM(E_UNEXPECTED);
  1012. }
  1013. if (direction != destdir) {
  1014. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() wrong direction");
  1015. return false;
  1016. }
  1017. DSPin pConn = pPin1.GetConnection();
  1018. if (!pConn) {
  1019. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() unconnected to anything");
  1020. return false;
  1021. }
  1022. PIN_INFO pinfo;
  1023. DSFilter PinFilter;
  1024. if (pConn) {
  1025. hr = pConn->QueryPinInfo(&pinfo);
  1026. PinFilter.p = pinfo.pFilter; // transfer refcount ownership
  1027. }
  1028. if (PinFilter == pFDestination) {
  1029. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() directly true");
  1030. return true;
  1031. }
  1032. #if 0
  1033. #if CRASH
  1034. DSFilter::iterator i = std::find_if(PinFilter.begin(),
  1035. PinFilter.end(),
  1036. bind_const_obj_2_3_4(
  1037. *this,
  1038. arity4_const_member(&DSGraph::IsPinConnected),
  1039. pFDestination,
  1040. IntermediatesAdded,
  1041. destdir));
  1042. #else
  1043. DSFilter::iterator i = std::find_if(PinFilter.begin(),
  1044. PinFilter.end(),
  1045. bndr_const_obj_2_3_4<arity4pmf_const<const DSGraph, const DSPin&, const DSFilter&, DSFilterIDList &, const PIN_DIRECTION, bool> >(
  1046. *this,
  1047. arity4_const_member(&DSGraph::IsPinConnected),
  1048. pFDestination,
  1049. IntermediatesAdded,
  1050. destdir));
  1051. #endif
  1052. if (i != PinFilter.end()) {
  1053. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() indirectly true");
  1054. return true;
  1055. }
  1056. #endif
  1057. for (DSFilter::iterator i = PinFilter.begin(); i != PinFilter.end(); ++i) {
  1058. if (IsPinConnected(*i, pFDestination, IntermediatesAdded, destdir)) {
  1059. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() indirectly true");
  1060. return true;
  1061. }
  1062. }
  1063. TRACELM(TRACE_DETAIL, "DSGraph::IsPinConnected() unconnected to desired dest");
  1064. return false;
  1065. }
  1066. #if 0
  1067. DSFilter DSGraph::LoadFilter(const PQMoniker &pM, CString &csName) {
  1068. TRACELM(TRACE_DETAIL, "DSGraph::LoadFilter()");
  1069. csName = _T("");
  1070. PQFilter pFilter;
  1071. PQPropertyBag pPropBag;
  1072. HRESULT hr = (pM)->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<LPVOID *>(&pPropBag));
  1073. if (FAILED(hr)) {
  1074. TRACELM(TRACE_ERROR, "DSGraph::LoadFilter() can't bind to storage");
  1075. THROWCOM(hr);
  1076. }
  1077. CComVariant vName;
  1078. vName.vt = VT_BSTR;
  1079. hr = pPropBag->Read(L"FriendlyName", &vName, NULL);
  1080. if (FAILED(hr)) {
  1081. TRACELM(TRACE_ERROR, "DSGraph::LoadFilter() can't read friendly name");
  1082. THROWCOM(hr);
  1083. }
  1084. USES_CONVERSION;
  1085. BSTR p = vName.bstrVal;
  1086. csName = OLE2T(p);
  1087. TRACELM(TRACE_DETAIL, "DSGraph::LoadFilter() have propbag");
  1088. hr = (pM)->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<LPVOID *>(&pFilter));
  1089. if (FAILED(hr)) {
  1090. TRACELM(TRACE_ERROR, "DSGraph::LoadFilter() can't bind to object");
  1091. THROWCOM(hr);
  1092. }
  1093. return pFilter;
  1094. }
  1095. #else
  1096. DSFilter DSGraph::LoadFilter(const DSFilterMoniker &pM, CString &csName) {
  1097. TRACELM(TRACE_DETAIL, "DSGraph::LoadFilter()");
  1098. CComBSTR p(pM.GetName());
  1099. if (p) {
  1100. USES_CONVERSION;
  1101. csName = OLE2T(p);
  1102. }
  1103. return pM.GetFilter();
  1104. }
  1105. #endif
  1106. DSFilter DSGraph::AddMoniker(const DSFilterMoniker &pM) {
  1107. TRACELM(TRACE_DETAIL, "DSGraph::AddMoniker()");
  1108. CString csName;
  1109. DSFilter pFilter = LoadFilter(pM, csName);
  1110. if (!pFilter) {
  1111. TRACELM(TRACE_ERROR, "DSGraph::AddMoniker() can't load filter");
  1112. return pFilter;
  1113. }
  1114. TRACELM(TRACE_DETAIL, "DSGraph::AddMoniker() have pFilter");
  1115. USES_CONVERSION;
  1116. HRESULT hr = (*this)->AddFilter(pFilter, T2COLE(csName));
  1117. if (FAILED(hr)) {
  1118. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::AddMoniker() can't add filter " << csName << " to graph"), "");
  1119. return DSFilter();
  1120. }
  1121. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::AddMoniker() added " << csName), "");
  1122. return pFilter;
  1123. }
  1124. HRESULT DSGraph::AddFilter(DSFilter &pFilter, CString &csName) {
  1125. TRACELM(TRACE_DETAIL, "DSGraph::AddFilter()");
  1126. HRESULT hr;
  1127. USES_CONVERSION;
  1128. hr = (*this)->AddFilter(pFilter, T2COLE(csName));
  1129. if (FAILED(hr)) {
  1130. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::AddFilter() can't add filter " << csName << " to graph"), "");
  1131. }
  1132. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::AddFilter() added " << csName), "");
  1133. return hr;
  1134. }
  1135. DSFilter DSGraph::AddFilter(const CLSID &cls, CString &csName) {
  1136. TRACELM(TRACE_DETAIL, "DSGraph::AddFilter()");
  1137. HRESULT hr;
  1138. DSFilter pFilter(cls, NULL, CLSCTX_INPROC_SERVER);
  1139. if (!pFilter) {
  1140. TRACELM(TRACE_ERROR, "DSGraph::AddFilter() can't create filter");
  1141. return pFilter;
  1142. }
  1143. hr = AddFilter(pFilter, csName);
  1144. if (FAILED(hr)) {
  1145. TRACELSM(TRACE_ERROR, (dbgDump << "DSGraph::AddFilter() can't add filter " << csName << " to graph"), "");
  1146. THROWCOM(hr);
  1147. }
  1148. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::AddFilter() added " << csName), "");
  1149. return pFilter;
  1150. }
  1151. // attempt to connect these two filters. if we fail we must remove
  1152. // any intermediate filters that we've added and leave the graph in the
  1153. // state we started with.
  1154. // only look at pFilter1 pins of pFilter1Direction
  1155. bool DSGraph::ConnectFilters(DSFilter &pFilter1, DSFilter &pFilter2, DSFilterIDList &IntermediatesAdded, DWORD dwFlags, PIN_DIRECTION pFilter1Direction) {
  1156. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectFilters() pFilter1 = " << pFilter1 << " pFilter2 = " << pFilter2), "");
  1157. if (pFilter1 == pFilter2) {
  1158. TRACELM(TRACE_DETAIL, "DSGraph::ConnectFilters same filter");
  1159. return false;
  1160. }
  1161. try {
  1162. TRACEINDENT();
  1163. // undone: there should be some way to preserve the info
  1164. // from the following check to speed up the actual connection in the event
  1165. // that they aren't already connected.
  1166. // see if these filters are already connected
  1167. DSFilter::iterator i;
  1168. if (!(dwFlags & IGNORE_EXISTING_CONNECTIONS)) {
  1169. #if 0
  1170. #if CRASH
  1171. i = std::find_if(pFilter1.begin(),
  1172. pFilter1.end(),
  1173. bind_obj_2_3_4(
  1174. *this,
  1175. arity4_const_member(&DSGraph::IsPinConnected),
  1176. pFilter2,
  1177. IntermediatesAdded,
  1178. pFilter1Direction));
  1179. #else
  1180. i = std::find_if(pFilter1.begin(),
  1181. pFilter1.end(),
  1182. bndr_const_obj_2_3_4<arity4pmf_const<const DSGraph, const DSPin&, const DSFilter&, DSFilterIDList &, const PIN_DIRECTION, bool> >(
  1183. *this,
  1184. arity4_const_member(&DSGraph::IsPinConnected),
  1185. pFilter2,
  1186. IntermediatesAdded,
  1187. pFilter1Direction));
  1188. #endif
  1189. if (i != pFilter1.end()) {
  1190. TRACEOUTDENT();
  1191. TRACELM(TRACE_DEBUG, "DSGraph::ConnectFilters already connected");
  1192. return true;
  1193. }
  1194. #endif
  1195. for (DSFilter::iterator i = pFilter1.begin(); i != pFilter1.end(); ++i) {
  1196. if (IsPinConnected(*i, pFilter2, IntermediatesAdded, pFilter1Direction)) {
  1197. TRACEOUTDENT();
  1198. TRACELM(TRACE_DEBUG, "DSGraph::ConnectFilters already connected");
  1199. return true;
  1200. }
  1201. }
  1202. }
  1203. // they're not connected so see if we can connect them
  1204. // connect every possible pin available and keep track of how many we connect
  1205. int cConnected = 0;
  1206. for (i = pFilter1.begin(); i != pFilter1.end(); ++i) {
  1207. try {
  1208. if (ConnectPin(DSPin(*i), pFilter2, IntermediatesAdded, dwFlags, pFilter1Direction)) {
  1209. TRACELM(TRACE_DETAIL, "DSGraph::ConnectFilters() pin connected");
  1210. cConnected++;
  1211. }
  1212. } catch(ComException &h) {
  1213. if (h != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) {
  1214. try {
  1215. TRACELM(TRACE_DETAIL, "DSGraph::ConnectFilters() rethrowing");
  1216. } catch(...) {
  1217. }
  1218. throw;
  1219. }
  1220. }
  1221. }
  1222. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectFilters() cConnected = " << cConnected), "");
  1223. if (cConnected) {
  1224. TRACEOUTDENT();// just inside try
  1225. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectFilters() succeeded pFilter1 = " << pFilter1 << " pFilter2 = " << pFilter2), "");
  1226. return true; // we connected at least one pin
  1227. }
  1228. TRACEOUTDENT();// just inside try
  1229. } catch (ComException &h) {
  1230. TRACEOUTDENT();// just inside try
  1231. if (h == E_UNEXPECTED) {
  1232. throw;
  1233. }
  1234. } catch (...) {
  1235. TRACEOUTDENT(); // just inside try
  1236. TRACELM(TRACE_DETAIL, "DSGraph::ConnectFilters() catch...");
  1237. }
  1238. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::ConnectFilters() failed pFilter1 = " << pFilter1 << " pFilter2 = " << pFilter2), "");
  1239. return false;
  1240. }
  1241. // this function returns a list of pairs of input and output points
  1242. // that must be connected to activate the shortest path between two filters
  1243. // it returns the number of connections in the path.
  1244. // i.e if start is adjacent to stop then rc is 1. if a single filter is between them then 2, etc.
  1245. // 0 indicates no path found.
  1246. int DSGraph::BuildGraphPath(const DSFilter& pStart,
  1247. const DSFilter& pStop,
  1248. VWStream &path,
  1249. MediaMajorTypeList& MediaTypes,
  1250. PIN_DIRECTION direction,
  1251. const DSPin &InitialInput)
  1252. {
  1253. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() start = " << pStart << " stop = " << pStop), "");
  1254. int pathlen = INT_MAX;
  1255. VWStream returnpath;
  1256. ASSERT(InitialInput || (!InitialInput && !pStart.IsXBar())); // first time in can't be an xbar unless original caller establishes InitialInput
  1257. for (DSFilter::iterator i = pStart.begin(); i != pStart.end(); ++i) {
  1258. DSPin pPin1(*i);
  1259. if (pPin1.GetDirection() != direction) {
  1260. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() " << pStart << ", " << pPin1 << " wrong direction"), "");
  1261. continue; // search forward
  1262. }
  1263. DSPin pConnection = pPin1.GetConnection();
  1264. if (!pConnection) {
  1265. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() " << pStart << ", " << pPin1 << " unconnected"), "");
  1266. continue;
  1267. }
  1268. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() checking " << pPin1 << " connected to " << pConnection.GetFilter() << " " << pConnection), "");
  1269. if (InitialInput) {
  1270. ASSERT(pPin1 != InitialInput); // direction check should already have filtered for this
  1271. DSMediaType amt(pPin1.GetConnectionMediaType());
  1272. ASSERT(amt);
  1273. if (amt->pUnk) {
  1274. amt->pUnk->Release();
  1275. }
  1276. MediaMajorTypeList::iterator l;
  1277. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() searching for " << GUID2(amt.p->majortype)), "");
  1278. l = std::find(MediaTypes.begin(), MediaTypes.end(), amt.p->majortype);
  1279. if (l == MediaTypes.end()) {
  1280. TRACELSM(TRACE_DETAIL, (dbgDump << "major media type not matched"), "");
  1281. continue;
  1282. }
  1283. if (!pPin1.CanRoute(InitialInput)) {
  1284. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() " << pStart << ", " << InitialInput << " Can't Route to " << pPin1), "");
  1285. continue;
  1286. }
  1287. }
  1288. DSFilter nextFilter = pConnection.GetFilter();
  1289. ASSERT(nextFilter);
  1290. TRACELSM(TRACE_PAINT, (dbgDump << "DSGraph::BuildGraphPath() nextFilter = " << nextFilter), "");
  1291. if (nextFilter == pStop) {
  1292. TRACELSM(TRACE_PAINT, (dbgDump << "DSGraph::BuildGraphPath() found stop filter"), "");
  1293. // we found the destination, we're done with this one
  1294. if (pStart.IsXBar()) {
  1295. // if we started on xbar then connected pin's outputpoint pairs with the
  1296. // initialinput(&pin) to form the first pair in the return path
  1297. TRACELM(TRACE_PAINT, "DSGraph::BuildGraphPath() pstart is xbar");
  1298. ASSERT(DSXBarPin(InitialInput));
  1299. PQPoint p1(DSXBarPin(InitialInput).GetPoint());
  1300. ASSERT(!!p1);
  1301. ASSERT(DSXBarPin(pPin1));
  1302. PQPoint p2(DSXBarPin(pPin1).GetPoint());
  1303. ASSERT(!!p2);
  1304. switch (direction) {
  1305. case DOWNSTREAM:
  1306. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::BuildGraphPath() saving pair (" << p1 << ", " << p2), ")");
  1307. returnpath.push_back(CIOPoint(p1, p2));
  1308. break;
  1309. case UPSTREAM:
  1310. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::BuildGraphPath() saving pair (" << p2 << ", " << p1), ")");
  1311. returnpath.push_back(CIOPoint(p2, p1));
  1312. break;
  1313. }
  1314. }
  1315. pathlen = 1;
  1316. break;
  1317. } else {
  1318. VWStream temp;
  1319. int rc = BuildGraphPath(nextFilter, pStop, temp, MediaTypes, direction, pConnection);
  1320. // undone: in win64 size() is really __int64. fix output operator for
  1321. // that type and remove cast
  1322. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::BuildGraphPath() recursed buildgraphpath returned rc = " << rc << " pathlen = " << pathlen << "sz = " << (long)temp.size()), "");
  1323. // if we found a path and the new one is shorter then the current one
  1324. if (rc && ((rc + 1) < pathlen)) {
  1325. TRACELM(TRACE_PAINT, "DSGraph::BuildGraphPath() accepting new path");
  1326. // save the new path
  1327. pathlen = rc + 1;
  1328. returnpath.clear();
  1329. TRACELM(TRACE_PAINT, "DSGraph::BuildGraphPath() checking xbar adjacency");
  1330. if (pStart.IsXBar()) {
  1331. // if we started on xbar then connected pin's outputpoint pairs with the
  1332. // initialinput(&pin) to form the next pair in the return path
  1333. TRACELM(TRACE_PAINT, "DSGraph::BuildGraphPath() pstart is xbar");
  1334. ASSERT(DSXBarPin(InitialInput));
  1335. PQPoint p1(DSXBarPin(InitialInput).GetPoint());
  1336. ASSERT(!!p1);
  1337. ASSERT(DSXBarPin(pPin1));
  1338. PQPoint p2(DSXBarPin(pPin1).GetPoint());
  1339. ASSERT(!!p2);
  1340. switch (direction) {
  1341. case DOWNSTREAM:
  1342. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::BuildGraphPath() saving pair (" << p1 << ", " << p2), ")");
  1343. returnpath.push_back(CIOPoint(p1, p2));
  1344. break;
  1345. case UPSTREAM:
  1346. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::BuildGraphPath() saving pair (" << p2 << ", " << p1), ")");
  1347. returnpath.push_back(CIOPoint(p2, p1));
  1348. break;
  1349. }
  1350. }
  1351. // append onto path any further downstream xbars found by recursion
  1352. returnpath.splice(returnpath.end(), temp);
  1353. } else {
  1354. TRACELM(TRACE_PAINT, "DSGraph::BuildGraphPath() discarding new path");
  1355. // keep the old return path and cleanup the temp one we just got back
  1356. temp.clear();
  1357. }
  1358. }
  1359. }
  1360. if (pathlen == INT_MAX) { // didn't find anything
  1361. return 0;
  1362. }
  1363. path = returnpath;
  1364. return pathlen;
  1365. }
  1366. HRESULT DSGraph::AddToROT(DWORD *pdwObjectRegistration) {
  1367. PQMoniker pGraphMK;
  1368. PQROT pROT;
  1369. if (FAILED(::GetRunningObjectTable(0, &pROT))) {
  1370. return E_UNEXPECTED;
  1371. }
  1372. OLECHAR osz[256];
  1373. // undone: in the ia64 case the following format spec isn't enough digits for an address
  1374. //wsprintfW(osz, OLESTR("FilterGraph %08lx pid %08lx"), (DWORD_PTR) this->p, ::GetCurrentProcessId());
  1375. HRESULT hr = StringCchPrintfW(osz, sizeof(osz) / sizeof(osz[0]), OLESTR("FilterGraph %08lx pid %08lx"), (DWORD_PTR) this->p, ::GetCurrentProcessId());
  1376. if(FAILED(hr)){
  1377. ASSERT(false);
  1378. }
  1379. hr = ::CreateItemMoniker(OLESTR("!"), osz, &pGraphMK);
  1380. if (SUCCEEDED(hr)) {
  1381. hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, *this, pGraphMK, pdwObjectRegistration);
  1382. }
  1383. return hr;
  1384. }
  1385. void DSGraph::RemoveFromROT(DWORD dwObjectRegistration) {
  1386. PQROT pROT;
  1387. if (SUCCEEDED(::GetRunningObjectTable(0, &pROT))) {
  1388. pROT->Revoke(dwObjectRegistration);
  1389. }
  1390. }
  1391. ///////////////////////////////////////////////////////////////////////////////////////////////
  1392. // DSFilter
  1393. ///////////////////////////////////////////////////////////////////////////////////////////////
  1394. DSGraph DSFilter::GetGraph(void) {
  1395. FILTER_INFO finfo;
  1396. HRESULT hr = (*this)->QueryFilterInfo(&finfo);
  1397. if (FAILED(hr)) {
  1398. TRACELM(TRACE_ERROR, "DSFilter::GetGraph() failed");
  1399. return DSGraph();
  1400. }
  1401. DSGraph graph = finfo.pGraph;
  1402. if (finfo.pGraph) finfo.pGraph->Release(); // transfer ref count
  1403. return graph;
  1404. }
  1405. ///////////////////////////////////////////////////////////////////////////////////////////////
  1406. // DSFilter
  1407. ///////////////////////////////////////////////////////////////////////////////////////////////
  1408. CString DSFilter::GetName(void) const {
  1409. CString csName;
  1410. FILTER_INFO finfo;
  1411. if (*this) {
  1412. HRESULT hr = (*this)->QueryFilterInfo(&finfo);
  1413. if (SUCCEEDED(hr)) {
  1414. csName = finfo.achName;
  1415. if (csName.IsEmpty()) {
  1416. csName = _T("");
  1417. }
  1418. if (finfo.pGraph) {
  1419. finfo.pGraph->Release();
  1420. }
  1421. } else {
  1422. #ifdef _DEBUG
  1423. csName = _T("**** UNKNOWN FILTER NAME ****");
  1424. #endif
  1425. }
  1426. } else {
  1427. #ifdef _DEBUG
  1428. csName = _T("**** NULL FILTER POINTER ****");
  1429. #endif
  1430. }
  1431. return csName;
  1432. }
  1433. void DSFilter::GetPinCounts(ULONG &ulIn, ULONG &ulOut) const
  1434. {
  1435. HRESULT hr;
  1436. ulIn = ulOut = 0;
  1437. PIN_DIRECTION pd;
  1438. DSFilter::iterator i;
  1439. for (i = begin(); i != end(); ++i) {
  1440. hr = (*i)->QueryDirection(&pd);
  1441. if (FAILED(hr)) {
  1442. TRACELSM(TRACE_ERROR, (dbgDump << "DSFilter:GetPinCounts() can't query pin direction hr = " << hr), "");
  1443. THROWCOM(E_UNEXPECTED);
  1444. }
  1445. switch (pd) {
  1446. case PINDIR_INPUT:
  1447. ulIn++;
  1448. break;
  1449. case PINDIR_OUTPUT:
  1450. ulOut++;
  1451. break;
  1452. }
  1453. }
  1454. return;
  1455. }
  1456. ///////////////////////////////////////////////////////////////////////////////////////////////
  1457. // DSPin
  1458. ///////////////////////////////////////////////////////////////////////////////////////////////
  1459. bool DSPin::HasCategory(const GUID2 &clsCategory, const PIN_DIRECTION pd) const {
  1460. TRACELSM(TRACE_DETAIL, (dbgDump << "DSPin::IsPinCategory() pin = " << this), "");
  1461. PIN_DIRECTION pd1;
  1462. HRESULT hr = (*this)->QueryDirection(&pd1);
  1463. if (FAILED(hr)) {
  1464. TRACELM(TRACE_ERROR, "DSPIN::IsPinCategeory() cant query Pin direction");
  1465. return false;
  1466. }
  1467. if (pd1 != pd) {
  1468. TRACELM(TRACE_ERROR, "DSPin::IsPinCategeory() wrong direction");
  1469. return false;
  1470. }
  1471. GUID2 pincat2;
  1472. GetCategory(pincat2);
  1473. return clsCategory == pincat2;
  1474. }
  1475. HRESULT DSPin::Connect(DSPin ConnectTo, const AM_MEDIA_TYPE *pMediaType) {
  1476. DSGraph pGraph = GetGraph();
  1477. DSGraph pConnGraph = ConnectTo.GetGraph();
  1478. ASSERT(pGraph);
  1479. ASSERT(pConnGraph);
  1480. ASSERT(pGraph == pConnGraph);
  1481. if (!pGraph || !pConnGraph || pGraph != pConnGraph) {
  1482. TRACELM(TRACE_ERROR, "DSPin::Connect() pins not in same graph");
  1483. THROWCOM(E_FAIL);
  1484. }
  1485. if (GetDirection() == PINDIR_OUTPUT) {
  1486. return pGraph->ConnectDirect(*this, ConnectTo, pMediaType);
  1487. } else {
  1488. return pGraph->ConnectDirect(ConnectTo, *this, pMediaType);
  1489. }
  1490. }
  1491. HRESULT DSPin::Disconnect(void) {
  1492. DSPin ConnectedTo;
  1493. HRESULT hr = (*this)->ConnectedTo(&ConnectedTo);
  1494. if (FAILED(hr) || !ConnectedTo) {
  1495. return NOERROR; // not connected to anything
  1496. }
  1497. PIN_INFO pinfo;
  1498. hr = (*this)->QueryPinInfo(&pinfo);
  1499. if (FAILED(hr)) {
  1500. TRACELM(TRACE_ERROR, "DSPin::Connect() can't call QueryPinInfo");
  1501. THROWCOM(E_UNEXPECTED);
  1502. }
  1503. DSFilter PinFilter;
  1504. PinFilter.p = pinfo.pFilter; // directly transfer ownership of ref count
  1505. DSGraph pGraph = PinFilter.GetGraph();
  1506. if (!pGraph) {
  1507. TRACELM(TRACE_ERROR, "DSPin::Disconnect() can't get graph from PinFilter");
  1508. THROWCOM(E_UNEXPECTED);
  1509. }
  1510. hr = pGraph->Disconnect(ConnectedTo);
  1511. if (FAILED(hr)) {
  1512. return hr;
  1513. }
  1514. return pGraph->Disconnect(*this);
  1515. }
  1516. // for any pin to possibly route they must be on the same filter and different directions
  1517. bool DSPin::Routable(const DSPin pin2) const {
  1518. if (GetFilter() != pin2.GetFilter()) {
  1519. return false;
  1520. }
  1521. if (GetDirection() == pin2.GetDirection()) {
  1522. return false;
  1523. }
  1524. return true;
  1525. }
  1526. bool DSPin::CanRoute(const DSPin pin2) const {
  1527. ASSERT(GetFilter() == pin2.GetFilter());
  1528. PQCrossbarSwitch px1(GetFilter());
  1529. if (!px1) {
  1530. return Routable(pin2);
  1531. }
  1532. return DSXBarPin(*this).CanRoute(DSXBarPin(pin2));
  1533. }
  1534. ///////////////////////////////////////////////////////////////////////////////////////////////
  1535. // DSXBarPin
  1536. ///////////////////////////////////////////////////////////////////////////////////////////////
  1537. #if 0
  1538. const DSXBarPin DSXBarPin::Find(const CPinPoints &pinpoints, const PQPoint &point, PIN_DIRECTION pindir) {
  1539. CPinPoints::const_iterator i;
  1540. TRACELSM(TRACE_DEBUG, (dbgDump << "DSXBarPin::Find() finding " << point << " direction = " << pindir), "");
  1541. for (i = pinpoints.begin(); i != pinpoints.end(); ++i) {
  1542. TRACELSM(TRACE_DEBUG, (dbgDump << "DSXBarPin::Find() checking " << DSPin((*i).first) << " direction " << DSPin((*i).first).GetDirection() << " " << (*i).second), "");
  1543. if ((*i).second == point && DSPin((*i).first).GetDirection() == pindir) {
  1544. DSPin p((*i).first);
  1545. PQCrossbarSwitch px1(p.GetFilter());
  1546. if (!px1) {
  1547. TRACELSM(TRACE_ERROR, (dbgDump << "DSXBarPin::Find() not an xbar " << p), "");
  1548. THROWCOM(E_FAIL);
  1549. }
  1550. TRACELSM(TRACE_DEBUG, (dbgDump << "DSXBarPin::Find() found " << p), "");
  1551. return DSXBarPin(p);
  1552. }
  1553. }
  1554. THROWCOM(E_FAIL);
  1555. return DSXBarPin();
  1556. }
  1557. #endif
  1558. // undone: cache this lookup
  1559. const PQPoint DSXBarPin::GetPoint() const {
  1560. DSFilter f= GetFilter();
  1561. PQCrossbarSwitch px(f);
  1562. if (!px) {
  1563. TRACELSM(TRACE_ERROR, (dbgDump << "DSXBarPin::Pin2Point() not an xbar" << *this), "");
  1564. THROWCOM(E_INVALIDARG);
  1565. }
  1566. PIN_DIRECTION dir = GetDirection();
  1567. long idx = 0;
  1568. DSFilter::iterator i;
  1569. for (i = f.begin(); i != f.end() && *i != *this; ++i) {
  1570. if ((*i).GetDirection() == dir) { // output idx's start over at 0
  1571. ++idx;
  1572. }
  1573. }
  1574. if (i != f.end()) {
  1575. TRACELSM(TRACE_PAINT, (dbgDump << "DSXBarPin::GetPoint() " << *this << " pt = " << idx), "");
  1576. return PQPoint(px, idx);
  1577. } else {
  1578. TRACELSM(TRACE_PAINT, (dbgDump << "DSXBarPin::GetPoint() No Point"), "");
  1579. return PQPoint();
  1580. }
  1581. }
  1582. bool DSXBarPin::CanRoute(const DSXBarPin pin2) const {
  1583. if (!Routable(pin2)) {
  1584. // pins not on same filter or both pins same direction
  1585. return false;
  1586. }
  1587. PQPoint pt1(GetPoint());
  1588. if (!pt1.first) {
  1589. // not on xbar or something corrupt
  1590. return false;
  1591. }
  1592. PQPoint pt2(pin2.GetPoint());
  1593. if (!pt2.first) {
  1594. // not on xbar or something corrupt
  1595. return false;
  1596. }
  1597. ASSERT(pt1.first == pt2.first); // must be on same xbar
  1598. HRESULT hr = E_FAIL;
  1599. switch(GetDirection()) {
  1600. case PINDIR_INPUT:
  1601. hr = (pt1.first)->CanRoute(pt2.second, pt1.second);
  1602. TRACELSM(TRACE_PAINT, (dbgDump << "DSXBarPin::CanRoute() in 2.sec " << pt2.second << " 1.sec " << pt1.second << " hr = " << hr), "");
  1603. break;
  1604. case PINDIR_OUTPUT:
  1605. hr = (pt1.first)->CanRoute(pt1.second, pt2.second);
  1606. TRACELSM(TRACE_PAINT, (dbgDump << "DSXBarPin::CanRoute() out 1.sec " << pt1.second << " 2.sec " << pt2.second << " hr = " << hr), "");
  1607. break;
  1608. }
  1609. return hr == S_OK;
  1610. }
  1611. void VWStream::Route() {
  1612. for (iterator i = begin(); i != end(); ++i) {
  1613. CIOPoint p(*i);
  1614. ASSERT(p.first.first == p.second.first);
  1615. PQCrossbarSwitch px(p.first.first);
  1616. HRESULT hr = px->Route(p.second.second, p.first.second);
  1617. ASSERT(SUCCEEDED(hr));
  1618. TRACELSM(TRACE_DETAIL, (dbgDump << "VWStream::Route() hr = " << hr << " px = " << px << " P.2.2 = " << p.second.second << " p.1.2 " << p.first.second), "");
  1619. }
  1620. }
  1621. bool IsVideoFilter(const DSFilter& f) {
  1622. DSFilter::iterator i;
  1623. for (i = f.begin(); i != f.end(); ++i) {
  1624. if (IsVideoPin(*i)) {
  1625. return true;
  1626. }
  1627. }
  1628. return false;
  1629. }
  1630. bool IsVideoPin(const DSPin& p) {
  1631. DSPin::iterator i;
  1632. for (i = p.begin(); i != p.end(); ++i) {
  1633. if (IsVideoMediaType(*i)) {
  1634. return true;
  1635. }
  1636. }
  1637. return false;
  1638. }
  1639. #if 0
  1640. // disable until we have pinpoints cache
  1641. void DSXBarPin::GetRelations(const CPinPoints &pinpoints, CString &csName, CString &csType, CString &csRelName) const {
  1642. TRACELSM(TRACE_DETAIL, (dbgDump << "DSXBarPin::GetRelations() examining xbar pin " << *this), "");
  1643. CString csw;
  1644. DSFilter f = GetFilter();
  1645. PQCrossbarSwitch xbar(f);
  1646. if (!xbar) {
  1647. THROWCOM(E_FAIL);
  1648. }
  1649. TRACELSM(TRACE_DETAIL, (dbgDump << "DSXBarPin::GetRelations() examining xbar filter" << f), "");
  1650. long rel, phys;
  1651. HRESULT hr = xbar->get_CrossbarPinInfo(IsInput(), Pin2Point(pinpoints).second, &rel, &phys);
  1652. if (FAILED(hr)) {
  1653. THROWCOM(hr);
  1654. }
  1655. TRACELSM(TRACE_DEBUG, (dbgDump << "DSXBarPin::GetRelations() have xbar info. pin = " << (*this) << " rel = " << rel << " phys = " << phys), "");
  1656. TCHAR tphys[256];
  1657. _ltot(phys, tphys, 10);
  1658. csName = GetName();
  1659. csType = tphys;
  1660. ULONG inc, outc;
  1661. f.GetPinCounts(inc, outc);
  1662. long pincount = inc + outc;
  1663. if (rel >= 0 && rel < pincount) {
  1664. DSXBarPin RelPin(Find(pinpoints, PQPoint(xbar, rel), (*this).GetDirection()));
  1665. if (!RelPin) {
  1666. TRACELSM(TRACE_DETAIL, (dbgDump << "DSXBarPin::GetRelations() can't build relpin. rel = " << rel), "");
  1667. } else {
  1668. csRelName = RelPin.GetName();
  1669. }
  1670. }
  1671. TRACELSM(TRACE_DEBUG, (dbgDump << "DSXBarPin::GetRelations() Name " << csName << " Type " << csType << " RelName " << csRelName), "");
  1672. return;
  1673. }
  1674. #endif
  1675. #ifdef _DEBUG
  1676. void DumpMediaTypes(DSPin &p1, DSPin &p2) {
  1677. DSPin::iterator i;
  1678. DumpHdr(dbgDump) << "DumpMediaTypes(): " << std::endl;
  1679. TRACEINDENT();
  1680. for (i = p1.begin(); i != p1.end(); ++i) {
  1681. DumpHdr(dbgDump) << (*i) << " " << hexdump(p2->QueryAccept(*i)) << std::endl;
  1682. }
  1683. DumpHdr(dbgDump) << "----" << std::endl;
  1684. for (i = p2.begin(); i != p2.end(); ++i) {
  1685. DumpHdr(dbgDump) << (*i) << " " << hexdump(p1->QueryAccept(*i)) << std::endl;
  1686. }
  1687. TRACEOUTDENT();
  1688. dbgDump.flush();
  1689. }
  1690. #endif
  1691. #pragma optimize("a", off)
  1692. bool DSGraph::LoadPinByMediaType(DSPin &pPin1, DSFilter &pFilter1, DSFilterIDList &IntermediatesAdded, const DWORD dwFlags, const DWORD dwMerit) {
  1693. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMediaType() pPin1 = " << pPin1 << " pFilter1 = " << pFilter1), "");
  1694. ASSERT(pPin1.GetGraph() == *this);
  1695. ASSERT(pFilter1.GetGraph() == *this);
  1696. GUID2* pInMedia = NULL;
  1697. GUID2* pOutMedia = NULL;
  1698. try {
  1699. TRACEINDENT();
  1700. // possibly in the future we should find all of the possible choices and
  1701. // use the shortest available path. but for now, we're just going to
  1702. // find the first one that exists
  1703. PIN_DIRECTION pd;
  1704. HRESULT hr = pPin1->QueryDirection(&pd);
  1705. if (FAILED(hr)) {
  1706. TRACEOUTDENT();
  1707. TRACELM(TRACE_ERROR, "DSGraph::LoadPinByMedium() can't query direction");
  1708. THROWCOM(E_UNEXPECTED);
  1709. }
  1710. PIN_DIRECTION pd2;
  1711. switch (pd) {
  1712. case PINDIR_INPUT:
  1713. pd2 = PINDIR_OUTPUT;
  1714. break;
  1715. case PINDIR_OUTPUT:
  1716. pd2 = PINDIR_INPUT;
  1717. break;
  1718. }
  1719. bool fInReq = false, fOutReq = false;
  1720. DWORD dwIn = 0;
  1721. DWORD dwOut = 0;
  1722. GUID2** ppMediaList = NULL;
  1723. DWORD dwMediaCount = 0;
  1724. for (DSPin::iterator i = pPin1.begin(); i != pPin1.end(); ++i) {
  1725. ++dwMediaCount;
  1726. }
  1727. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMediaType() pindir = " << pd << " mediacount = " << dwMediaCount), "");
  1728. switch (pd) {
  1729. case PINDIR_INPUT:
  1730. // hunting through graph from right to left
  1731. fOutReq = true;
  1732. dwOut = dwMediaCount;
  1733. pOutMedia = new GUID2[dwOut * 2];
  1734. ppMediaList = &pOutMedia;
  1735. break;
  1736. case PINDIR_OUTPUT:
  1737. // hunting through graph from left to right
  1738. fInReq = true;
  1739. dwIn = dwMediaCount;
  1740. pInMedia = new GUID2[dwIn * 2];
  1741. ppMediaList = &pInMedia;
  1742. break;
  1743. }
  1744. DWORD idx = 0;
  1745. // note: some buggy filters don't support the reuse of an IEnumMediaTypes even though
  1746. // reset succeeds. they AV during the next pass through the enumerator. thus, we
  1747. // just create a new iterator which fetches a new IEnumMediaTypes interface(and underlying object)
  1748. for (DSPin::iterator i2 = pPin1.begin(); i2 != pPin1.end(); ++i2) {
  1749. (*ppMediaList)[idx++] = (*i2)->majortype;
  1750. (*ppMediaList)[idx++] = (*i2)->subtype;
  1751. }
  1752. TRACELM(TRACE_DETAIL, "DSGraph::LoadPinByMediaType() dwFlags = " << hexdump(dwFlags) << " Merit = " << hexdump(dwMerit) << " MediaList = ");
  1753. TRACEINDENT();
  1754. for (idx = 0; idx < dwMediaCount; ++idx) {
  1755. TRACELSM(TRACE_DETAIL, (dbgDump << "major = " << (*ppMediaList)[idx * 2] << " sub = " << (*ppMediaList)[(idx * 2) + 1] ), "");
  1756. }
  1757. TRACEOUTDENT();
  1758. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMediaType() fInReq = " << fInReq), "");
  1759. TRACELSM(TRACE_DETAIL, (dbgDump << "DSGraph::LoadPinByMediaType() fOutReq = " << fOutReq), "");
  1760. // try normal first
  1761. {DSFilterMapper fmr(PQFilterMapper(*this),
  1762. 0, // 0 flags
  1763. !(dwFlags & ALLOW_WILDCARDS), // bExactMatch
  1764. dwMerit, // merit
  1765. fInReq, // input required
  1766. dwIn,
  1767. pInMedia,
  1768. NULL, // input medium
  1769. NULL, // input pin cat
  1770. false, // input rendered?
  1771. fOutReq, // output required
  1772. dwOut,
  1773. pOutMedia,
  1774. NULL, // output medium
  1775. NULL // output pin cat
  1776. );
  1777. if (fmr) {
  1778. // direct connect
  1779. for (DSFilterMapper::iterator i = fmr.begin(); i != fmr.end(); ++i) {
  1780. #ifdef ATTEMPT_DIRECT_CONNECT
  1781. if (IsLoadable(pPin1, DSFilterMoniker(*i), pFilter1, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinDirect))) {
  1782. #else
  1783. if (IsLoadable(pPin1, DSFilterMoniker(*i), pFilter1, IntermediatesAdded, dwFlags, ConnectPred_t(&DSGraph::ConnectPinByMediaType))) {
  1784. #endif
  1785. TRACEOUTDENT();
  1786. TRACELM(TRACE_ERROR, "DSGraph::LoadPinByMediaType() succeeded");
  1787. delete[] pInMedia;
  1788. delete[] pOutMedia;
  1789. return true;
  1790. }
  1791. }
  1792. }}
  1793. TRACEOUTDENT();
  1794. } catch(ComException& h) {
  1795. TRACEOUTDENT();
  1796. if ((h == E_UNEXPECTED) ||
  1797. (h == HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH)) ||
  1798. (h == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
  1799. ) {
  1800. try {
  1801. delete[] pInMedia;
  1802. delete[] pOutMedia;
  1803. TRACELM(TRACE_DEBUG, "DSGraph::LoadPinByMediaType() rethrowing");
  1804. } catch(...) {
  1805. }
  1806. throw;
  1807. }
  1808. try {
  1809. TRACELSM(TRACE_DEBUG, (dbgDump << "DSGraph::LoadPinByMediaType() suppressing HRESULT = " << hexdump(h)), "");
  1810. } catch(...) {
  1811. }
  1812. } catch(...) {
  1813. TRACEOUTDENT();
  1814. }
  1815. delete[] pInMedia;
  1816. delete[] pOutMedia;
  1817. TRACELM(TRACE_ERROR, "DSGraph::LoadPinByMediaType() failed");
  1818. return false;
  1819. }
  1820. #endif //TUNING_MODEL_ONLY
  1821. // end of file - dsextend.cpp