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.

1170 lines
33 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: sni.cpp
  4. //
  5. // Description:
  6. //
  7. // Start Node Instance
  8. //
  9. //@@BEGIN_MSINTERNAL
  10. // Development Team:
  11. // Mike McLaughlin
  12. //
  13. // History: Date Author Comment
  14. //
  15. // To Do: Date Author Comment
  16. //
  17. //@@END_MSINTERNAL
  18. //
  19. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  20. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  22. // PURPOSE.
  23. //
  24. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  25. //
  26. //---------------------------------------------------------------------------
  27. #include "common.h"
  28. //---------------------------------------------------------------------------
  29. WAVEFORMATEX aWaveFormatEx[] = {
  30. {
  31. WAVE_FORMAT_PCM, // wFormatTag
  32. 2, // nChannels
  33. 44100, // nSamplesPerSec
  34. 0, // nAvgBytesPerSec
  35. 0, // nBlockAlign
  36. 16, // wBitsPerSample
  37. 0, // cbSize
  38. },
  39. {
  40. WAVE_FORMAT_PCM, // wFormatTag
  41. 1, // nChannels
  42. 44100, // nSamplesPerSec
  43. 0, // nAvgBytesPerSec
  44. 0, // nBlockAlign
  45. 16, // wBitsPerSample
  46. 0, // cbSize
  47. },
  48. {
  49. WAVE_FORMAT_PCM, // wFormatTag
  50. 2, // nChannels
  51. 44100, // nSamplesPerSec
  52. 0, // nAvgBytesPerSec
  53. 0, // nBlockAlign
  54. 8, // wBitsPerSample
  55. 0, // cbSize
  56. },
  57. {
  58. WAVE_FORMAT_PCM, // wFormatTag
  59. 1, // nChannels
  60. 44100, // nSamplesPerSec
  61. 0, // nAvgBytesPerSec
  62. 0, // nBlockAlign
  63. 8, // wBitsPerSample
  64. 0, // cbSize
  65. },
  66. {
  67. WAVE_FORMAT_PCM, // wFormatTag
  68. 2, // nChannels
  69. 48000, // nSamplesPerSec
  70. 0, // nAvgBytesPerSec
  71. 0, // nBlockAlign
  72. 16, // wBitsPerSample
  73. 0, // cbSize
  74. },
  75. {
  76. WAVE_FORMAT_PCM, // wFormatTag
  77. 1, // nChannels
  78. 48000, // nSamplesPerSec
  79. 0, // nAvgBytesPerSec
  80. 0, // nBlockAlign
  81. 16, // wBitsPerSample
  82. 0, // cbSize
  83. },
  84. {
  85. WAVE_FORMAT_PCM, // wFormatTag
  86. 2, // nChannels
  87. 48000, // nSamplesPerSec
  88. 0, // nAvgBytesPerSec
  89. 0, // nBlockAlign
  90. 8, // wBitsPerSample
  91. 0, // cbSize
  92. },
  93. {
  94. WAVE_FORMAT_PCM, // wFormatTag
  95. 1, // nChannels
  96. 48000, // nSamplesPerSec
  97. 0, // nAvgBytesPerSec
  98. 0, // nBlockAlign
  99. 8, // wBitsPerSample
  100. 0, // cbSize
  101. },
  102. {
  103. WAVE_FORMAT_PCM, // wFormatTag
  104. 2, // nChannels
  105. 32000, // nSamplesPerSec
  106. 0, // nAvgBytesPerSec
  107. 0, // nBlockAlign
  108. 16, // wBitsPerSample
  109. 0, // cbSize
  110. },
  111. {
  112. WAVE_FORMAT_PCM, // wFormatTag
  113. 1, // nChannels
  114. 32000, // nSamplesPerSec
  115. 0, // nAvgBytesPerSec
  116. 0, // nBlockAlign
  117. 16, // wBitsPerSample
  118. 0, // cbSize
  119. },
  120. {
  121. WAVE_FORMAT_PCM, // wFormatTag
  122. 2, // nChannels
  123. 32000, // nSamplesPerSec
  124. 0, // nAvgBytesPerSec
  125. 0, // nBlockAlign
  126. 8, // wBitsPerSample
  127. 0, // cbSize
  128. },
  129. {
  130. WAVE_FORMAT_PCM, // wFormatTag
  131. 1, // nChannels
  132. 32000, // nSamplesPerSec
  133. 0, // nAvgBytesPerSec
  134. 0, // nBlockAlign
  135. 8, // wBitsPerSample
  136. 0, // cbSize
  137. },
  138. {
  139. WAVE_FORMAT_PCM, // wFormatTag
  140. 2, // nChannels
  141. 22050, // nSamplesPerSec
  142. 0, // nAvgBytesPerSec
  143. 0, // nBlockAlign
  144. 16, // wBitsPerSample
  145. 0, // cbSize
  146. },
  147. {
  148. WAVE_FORMAT_PCM, // wFormatTag
  149. 1, // nChannels
  150. 22050, // nSamplesPerSec
  151. 0, // nAvgBytesPerSec
  152. 0, // nBlockAlign
  153. 16, // wBitsPerSample
  154. 0, // cbSize
  155. },
  156. {
  157. WAVE_FORMAT_PCM, // wFormatTag
  158. 2, // nChannels
  159. 22050, // nSamplesPerSec
  160. 0, // nAvgBytesPerSec
  161. 0, // nBlockAlign
  162. 8, // wBitsPerSample
  163. 0, // cbSize
  164. },
  165. {
  166. WAVE_FORMAT_PCM, // wFormatTag
  167. 1, // nChannels
  168. 22050, // nSamplesPerSec
  169. 0, // nAvgBytesPerSec
  170. 0, // nBlockAlign
  171. 8, // wBitsPerSample
  172. 0, // cbSize
  173. },
  174. {
  175. WAVE_FORMAT_PCM, // wFormatTag
  176. 2, // nChannels
  177. 16000, // nSamplesPerSec
  178. 0, // nAvgBytesPerSec
  179. 0, // nBlockAlign
  180. 16, // wBitsPerSample
  181. 0, // cbSize
  182. },
  183. {
  184. WAVE_FORMAT_PCM, // wFormatTag
  185. 1, // nChannels
  186. 16000, // nSamplesPerSec
  187. 0, // nAvgBytesPerSec
  188. 0, // nBlockAlign
  189. 16, // wBitsPerSample
  190. 0, // cbSize
  191. },
  192. {
  193. WAVE_FORMAT_PCM, // wFormatTag
  194. 2, // nChannels
  195. 16000, // nSamplesPerSec
  196. 0, // nAvgBytesPerSec
  197. 0, // nBlockAlign
  198. 8, // wBitsPerSample
  199. 0, // cbSize
  200. },
  201. {
  202. WAVE_FORMAT_PCM, // wFormatTag
  203. 1, // nChannels
  204. 16000, // nSamplesPerSec
  205. 0, // nAvgBytesPerSec
  206. 0, // nBlockAlign
  207. 8, // wBitsPerSample
  208. 0, // cbSize
  209. },
  210. {
  211. WAVE_FORMAT_PCM, // wFormatTag
  212. 2, // nChannels
  213. 11025, // nSamplesPerSec
  214. 0, // nAvgBytesPerSec
  215. 0, // nBlockAlign
  216. 16, // wBitsPerSample
  217. 0, // cbSize
  218. },
  219. {
  220. WAVE_FORMAT_PCM, // wFormatTag
  221. 1, // nChannels
  222. 11025, // nSamplesPerSec
  223. 0, // nAvgBytesPerSec
  224. 0, // nBlockAlign
  225. 16, // wBitsPerSample
  226. 0, // cbSize
  227. },
  228. {
  229. WAVE_FORMAT_PCM, // wFormatTag
  230. 2, // nChannels
  231. 11025, // nSamplesPerSec
  232. 0, // nAvgBytesPerSec
  233. 0, // nBlockAlign
  234. 8, // wBitsPerSample
  235. 0, // cbSize
  236. },
  237. {
  238. WAVE_FORMAT_PCM, // wFormatTag
  239. 1, // nChannels
  240. 11025, // nSamplesPerSec
  241. 0, // nAvgBytesPerSec
  242. 0, // nBlockAlign
  243. 8, // wBitsPerSample
  244. 0, // cbSize
  245. },
  246. {
  247. WAVE_FORMAT_PCM, // wFormatTag
  248. 2, // nChannels
  249. 8000, // nSamplesPerSec
  250. 0, // nAvgBytesPerSec
  251. 0, // nBlockAlign
  252. 16, // wBitsPerSample
  253. 0, // cbSize
  254. },
  255. {
  256. WAVE_FORMAT_PCM, // wFormatTag
  257. 1, // nChannels
  258. 8000, // nSamplesPerSec
  259. 0, // nAvgBytesPerSec
  260. 0, // nBlockAlign
  261. 16, // wBitsPerSample
  262. 0, // cbSize
  263. },
  264. {
  265. WAVE_FORMAT_PCM, // wFormatTag
  266. 2, // nChannels
  267. 8000, // nSamplesPerSec
  268. 0, // nAvgBytesPerSec
  269. 0, // nBlockAlign
  270. 8, // wBitsPerSample
  271. 0, // cbSize
  272. },
  273. {
  274. WAVE_FORMAT_PCM, // wFormatTag
  275. 1, // nChannels
  276. 8000, // nSamplesPerSec
  277. 0, // nAvgBytesPerSec
  278. 0, // nBlockAlign
  279. 8, // wBitsPerSample
  280. 0, // cbSize
  281. },
  282. };
  283. //---------------------------------------------------------------------------
  284. //---------------------------------------------------------------------------
  285. NTSTATUS
  286. CStartNodeInstance::Create(
  287. PPIN_INSTANCE pPinInstance,
  288. PSTART_NODE pStartNode,
  289. PKSPIN_CONNECT pPinConnect,
  290. PWAVEFORMATEX pWaveFormatExRequested
  291. )
  292. {
  293. PSTART_NODE_INSTANCE pStartNodeInstance = NULL;
  294. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  295. Assert(pPinInstance);
  296. Assert(pStartNode);
  297. Assert(pStartNode->pPinNode);
  298. DPF3(90, "CSNI::Create SN %08x #%d %s",
  299. pStartNode,
  300. pStartNode->pPinNode->pPinInfo->PinId,
  301. pStartNode->pPinNode->pPinInfo->pFilterNode->DumpName());
  302. #ifdef DEBUG
  303. DumpDataRange(95, (PKSDATARANGE_AUDIO)pStartNode->pPinNode->pDataRange);
  304. #endif
  305. //
  306. // First few checks compare the StartNode datarange to pPinConnect
  307. // datarange.
  308. //
  309. if(!CompareIdentifier(
  310. pStartNode->pPinNode->pMedium,
  311. &pPinConnect->Medium)) {
  312. Trap();
  313. DPF1(90, "CSNI::Create: Medium %08X", pStartNode);
  314. ASSERT(Status == STATUS_INVALID_DEVICE_REQUEST);
  315. goto exit;
  316. }
  317. if(!CompareIdentifier(
  318. pStartNode->pPinNode->pInterface,
  319. &pPinConnect->Interface)) {
  320. DPF1(90, "CSNI::Create: Interface %08X", pStartNode);
  321. ASSERT(Status == STATUS_INVALID_DEVICE_REQUEST);
  322. goto exit;
  323. }
  324. if(!CompareDataRangeGuids(
  325. pStartNode->pPinNode->pDataRange,
  326. (PKSDATARANGE)(pPinConnect + 1))) {
  327. DPF1(90, "CSNI::Create: DataRange GUID %08X", pStartNode);
  328. ASSERT(Status == STATUS_INVALID_DEVICE_REQUEST);
  329. goto exit;
  330. }
  331. //
  332. // VOICE MANAGEMENT and HW ACCELARATION
  333. // For HW accelarated pins we are not relying on local sysaudio
  334. // instance counts. PinCreate request will be sent down to the driver.
  335. // It is upto the driver to reject the request based on its capabilities.
  336. //
  337. if ((pStartNode->pPinNode->pPinInfo->pFilterNode->GetType() & FILTER_TYPE_RENDERER) &&
  338. (KSPIN_DATAFLOW_IN == pStartNode->pPinNode->pPinInfo->DataFlow) &&
  339. (KSPIN_COMMUNICATION_SINK == pStartNode->pPinNode->pPinInfo->Communication)) {
  340. DPF(20,"StartInfo::IsPinInstances return TRUE for HW");
  341. }
  342. else {
  343. if(!pStartNode->IsPinInstances()) {
  344. DPF1(90, "CSNI::Create: no instances SN %08X", pStartNode);
  345. Status = STATUS_DEVICE_BUSY;
  346. goto exit;
  347. }
  348. }
  349. pStartNodeInstance = new START_NODE_INSTANCE(pPinInstance, pStartNode);
  350. if(pStartNodeInstance == NULL) {
  351. Status = STATUS_INSUFFICIENT_RESOURCES;
  352. goto exit;
  353. }
  354. //
  355. // If capture pin, try some intelligent variations of requested format
  356. //
  357. if(!NT_SUCCESS(Status) &&
  358. pWaveFormatExRequested != NULL &&
  359. pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  360. DPF(90, "CSNI::Create: IntelligentConnect");
  361. Status = pStartNodeInstance->IntelligentConnect(
  362. pPinInstance->pFilterInstance->GetDeviceNode(),
  363. pPinConnect,
  364. pWaveFormatExRequested);
  365. //
  366. // If the graph contains only splitter and capturer, only the
  367. // requested format can succeed.
  368. // So exit here.
  369. //
  370. if (pStartNodeInstance->pStartNode->IsCaptureFormatStrict()) {
  371. DPF1(50, "CSNI::Create: CaptureFormatStrict Bailing Out: Status %X", Status);
  372. goto exit;
  373. }
  374. }
  375. //
  376. // If capture pin and if aec is included, negotiate format between
  377. // aec and capture device.
  378. //
  379. if(!NT_SUCCESS(Status) &&
  380. pStartNode->IsAecIncluded() &&
  381. pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  382. PKSPIN_CONNECT pPinConnectDirect = NULL;
  383. DPF(90, "CSNI::Create: AecConnection");
  384. Status = pStartNodeInstance->AecConnectionFormat(
  385. pPinInstance->pFilterInstance->GetDeviceNode(),
  386. &pPinConnectDirect);
  387. //
  388. // Try mono/stereo formats first.
  389. //
  390. if (NT_SUCCESS(Status)) {
  391. for (WORD i = 1; i <= 2; i++) {
  392. ModifyPinConnect(pPinConnectDirect, i);
  393. Status = pStartNodeInstance->Connect(
  394. pPinInstance->pFilterInstance->GetDeviceNode(),
  395. pPinConnect,
  396. NULL,
  397. pPinConnectDirect);
  398. if (NT_SUCCESS(Status)) {
  399. break;
  400. }
  401. }
  402. }
  403. if (pPinConnectDirect) {
  404. delete pPinConnectDirect;
  405. }
  406. }
  407. //
  408. // Try pin data intersection
  409. //
  410. if(!NT_SUCCESS(Status)) {
  411. DPF(90, "CSNI::Create: Data Intersection");
  412. Status = pStartNodeInstance->Connect(
  413. pPinInstance->pFilterInstance->GetDeviceNode(),
  414. pPinConnect,
  415. NULL,
  416. NULL);
  417. }
  418. if(!NT_SUCCESS(Status)) {
  419. int i;
  420. //
  421. // Try each waveformatex limit until success
  422. //
  423. for(i = 0; i < SIZEOF_ARRAY(aWaveFormatEx); i++) {
  424. DPF3(90, "CSNI::Create: Array SR %d CH %d BPS %d",
  425. aWaveFormatEx[i].nSamplesPerSec,
  426. aWaveFormatEx[i].nChannels,
  427. aWaveFormatEx[i].wBitsPerSample);
  428. Status = pStartNodeInstance->Connect(
  429. pPinInstance->pFilterInstance->GetDeviceNode(),
  430. pPinConnect,
  431. &aWaveFormatEx[i],
  432. NULL);
  433. if(NT_SUCCESS(Status)) {
  434. break;
  435. }
  436. }
  437. }
  438. if(!NT_SUCCESS(Status)) {
  439. goto exit;
  440. }
  441. //
  442. // Now all the pins in the graph are connected successfully.
  443. // Create the topology table.
  444. //
  445. Status = pStartNodeInstance->CreateTopologyTable(
  446. pPinInstance->pFilterInstance->pGraphNodeInstance);
  447. if(!NT_SUCCESS(Status)) {
  448. Trap();
  449. goto exit;
  450. }
  451. ASSERT(pStartNodeInstance->CurrentState == KSSTATE_STOP);
  452. DPF1(90, "CSNI::Create: SUCCESS %08x", pStartNodeInstance);
  453. exit:
  454. if(!NT_SUCCESS(Status)) {
  455. DPF1(90, "CSNI::Create: FAIL %08x", Status);
  456. delete pStartNodeInstance;
  457. }
  458. return(Status);
  459. }
  460. CStartNodeInstance::CStartNodeInstance(
  461. PPIN_INSTANCE pPinInstance,
  462. PSTART_NODE pStartNode
  463. )
  464. {
  465. this->pStartNode = pStartNode;
  466. pStartNode->AddPinInstance();
  467. this->pPinInstance = pPinInstance;
  468. pPinInstance->pStartNodeInstance = this;
  469. AddList(
  470. &pPinInstance->pFilterInstance->pGraphNodeInstance->lstStartNodeInstance);
  471. }
  472. CStartNodeInstance::~CStartNodeInstance(
  473. )
  474. {
  475. PINSTANCE pInstance;
  476. ASSERT(this != NULL);
  477. Assert(this);
  478. Assert(pPinInstance);
  479. DPF1(95, "~CSNI: %08x", this);
  480. RemoveList();
  481. SetState(KSSTATE_STOP, SETSTATE_FLAG_IGNORE_ERROR);
  482. pStartNode->RemovePinInstance();
  483. if (pPinNodeInstance)
  484. {
  485. pPinNodeInstance->Destroy(); // also see CSNI::CleanUp
  486. }
  487. if (pFilterNodeInstance)
  488. {
  489. pFilterNodeInstance->Destroy();
  490. }
  491. delete [] papFileObjectTopologyTable;
  492. delete pVirtualNodeData;
  493. pPinInstance->pStartNodeInstance = NULL;
  494. pPinInstance->ParentInstance.Invalidate();
  495. }
  496. VOID
  497. CStartNodeInstance::CleanUp(
  498. )
  499. {
  500. Assert(this);
  501. ASSERT(papFileObjectTopologyTable == NULL);
  502. ASSERT(pVirtualNodeData == NULL);
  503. ASSERT(CurrentState == KSSTATE_STOP);
  504. if (pPinNodeInstance)
  505. {
  506. pPinNodeInstance->Destroy();
  507. pPinNodeInstance = NULL;
  508. }
  509. if (pFilterNodeInstance)
  510. {
  511. pFilterNodeInstance->Destroy();
  512. pFilterNodeInstance = NULL;
  513. }
  514. lstConnectNodeInstance.DestroyList();
  515. }
  516. NTSTATUS
  517. CStartNodeInstance::IntelligentConnect(
  518. PDEVICE_NODE pDeviceNode,
  519. PKSPIN_CONNECT pPinConnect,
  520. PWAVEFORMATEX pWaveFormatEx
  521. )
  522. {
  523. PWAVEFORMATEXTENSIBLE pWaveFormatExtensible;
  524. NTSTATUS Status;
  525. BOOL Continue;
  526. WORD NumChannels, BitWidth;
  527. PBYTE pWaveFormat = NULL;
  528. ULONG RegionAllocSize, RegionCopySize;
  529. BOOL IsFloat = FALSE;
  530. WORD MaxBitWidth, MinBitWidth, MaxChannels, MinChannels;
  531. //
  532. // First copy the user requested format into a local structure
  533. // (because we will tamper it later for different params)
  534. //
  535. if (pWaveFormatEx->wFormatTag == WAVE_FORMAT_PCM) {
  536. RegionAllocSize = sizeof(WAVEFORMATEX);
  537. RegionCopySize = sizeof(PCMWAVEFORMAT);
  538. }
  539. else {
  540. RegionAllocSize = sizeof(WAVEFORMATEX) + pWaveFormatEx->cbSize;
  541. RegionCopySize = RegionAllocSize;
  542. }
  543. pWaveFormat = new(BYTE[RegionAllocSize]);
  544. if (!pWaveFormat) {
  545. Status = STATUS_INSUFFICIENT_RESOURCES;
  546. goto exit;
  547. }
  548. RtlCopyMemory(pWaveFormat, pWaveFormatEx, RegionCopySize);
  549. //
  550. // cast for convenient access
  551. //
  552. pWaveFormatExtensible = (PWAVEFORMATEXTENSIBLE) pWaveFormat;
  553. if (pWaveFormatExtensible->Format.wFormatTag == WAVE_FORMAT_PCM) {
  554. pWaveFormatExtensible->Format.cbSize = 0;
  555. }
  556. DPF3(90, "CSNI::Create: Client SR %d CH %d BPS %d",
  557. pWaveFormatExtensible->Format.nSamplesPerSec,
  558. pWaveFormatExtensible->Format.nChannels,
  559. pWaveFormatExtensible->Format.wBitsPerSample);
  560. //
  561. // and try the requested format first
  562. //
  563. Status = this->Connect(
  564. pDeviceNode,
  565. pPinConnect,
  566. (PWAVEFORMATEX)pWaveFormatEx,
  567. NULL);
  568. //
  569. // If the graph contains only splitter and capturer, only the
  570. // requested format can succeed.
  571. // So exit here.
  572. //
  573. if (pStartNode->IsCaptureFormatStrict()) {
  574. goto exit;
  575. }
  576. if (pWaveFormatExtensible->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
  577. IsFloat = TRUE;
  578. }
  579. if (pWaveFormatExtensible->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
  580. if (IsEqualGUID(&pWaveFormatExtensible->SubFormat,&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
  581. IsFloat = TRUE;
  582. }
  583. }
  584. if (IsFloat == FALSE) {
  585. if (pWaveFormatExtensible->Format.wFormatTag != WAVE_FORMAT_PCM) {
  586. if (pWaveFormatExtensible->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) {
  587. goto exit;
  588. }
  589. else {
  590. if (!IsEqualGUID(&pWaveFormatExtensible->SubFormat,&KSDATAFORMAT_SUBTYPE_PCM)) {
  591. goto exit;
  592. }
  593. }
  594. }
  595. MaxBitWidth =
  596. (pWaveFormatExtensible->Format.wBitsPerSample>16) ?
  597. pWaveFormatExtensible->Format.wBitsPerSample:16;
  598. MinBitWidth = 8;
  599. }
  600. else {
  601. MaxBitWidth = MinBitWidth = pWaveFormatEx->wBitsPerSample;
  602. }
  603. //
  604. // ISSUE: 02/20/02 ALPERS
  605. // The channel logic might not work with micarrays which have more than
  606. // two channels.
  607. //
  608. //
  609. // MaxChannels = (pWaveFormatExtensible->nChannels > 2) ? pWaveFormatExtensible->nChannels:2;
  610. // We can do this, what would be the channel mask for WaveFormatExtensible?
  611. //
  612. MaxChannels = 2;
  613. MinChannels = 1;
  614. //
  615. // If that failed with the same sample rate try different
  616. // combinations of numchannels & bitwidth
  617. //
  618. // Tries 4 combinations of STEREO/MONO & 8/16 bits
  619. // More intelligence can be built based upon device capability
  620. // (also does not check whether we tried a combination earlier)
  621. //
  622. if (!NT_SUCCESS(Status)) {
  623. Continue = TRUE;
  624. for (NumChannels = MaxChannels; (NumChannels >= MinChannels) && Continue; NumChannels--) {
  625. for (BitWidth = MaxBitWidth;
  626. (BitWidth >= MinBitWidth) && Continue;
  627. BitWidth=(BitWidth%8)?((BitWidth/8)*8):(BitWidth-8)) {
  628. pWaveFormatExtensible->Format.nChannels = NumChannels;
  629. pWaveFormatExtensible->Format.wBitsPerSample = BitWidth;
  630. pWaveFormatExtensible->Format.nBlockAlign = (NumChannels * BitWidth)/8;
  631. pWaveFormatExtensible->Format.nAvgBytesPerSec =
  632. pWaveFormatExtensible->Format.nSamplesPerSec *
  633. pWaveFormatExtensible->Format.nBlockAlign;
  634. if (pWaveFormatExtensible->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
  635. pWaveFormatExtensible->Samples.wValidBitsPerSample = BitWidth;
  636. if (NumChannels == 1) {
  637. pWaveFormatExtensible->dwChannelMask = SPEAKER_FRONT_CENTER;
  638. }
  639. else {
  640. pWaveFormatExtensible->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
  641. }
  642. }
  643. DPF3(90, "CSNI::Create: Client SR %d CH %d BPS %d",
  644. pWaveFormatExtensible->Format.nSamplesPerSec,
  645. pWaveFormatExtensible->Format.nChannels,
  646. pWaveFormatExtensible->Format.wBitsPerSample);
  647. Status = this->Connect(pDeviceNode,
  648. pPinConnect,
  649. (PWAVEFORMATEX)pWaveFormatExtensible,
  650. NULL);
  651. if (NT_SUCCESS(Status)) {
  652. Continue = FALSE;
  653. }
  654. }
  655. }
  656. }
  657. exit:
  658. delete [] pWaveFormat;
  659. return(Status);
  660. }
  661. NTSTATUS
  662. CStartNodeInstance::AecConnectionFormat(
  663. PDEVICE_NODE pDeviceNode,
  664. PKSPIN_CONNECT *ppPinConnect)
  665. {
  666. PCLIST_ITEM pListItem;
  667. PCONNECT_NODE_INSTANCE pConnectNodeInstance;
  668. PCONNECT_NODE_INSTANCE pBottomConnection;
  669. PCONNECT_NODE_INSTANCE pAecConnection = NULL;
  670. NTSTATUS Status = STATUS_SUCCESS;
  671. ASSERT(ppPinConnect);
  672. *ppPinConnect = NULL;
  673. Status = CConnectNodeInstance::Create(this, pDeviceNode);
  674. if(!NT_SUCCESS(Status)) {
  675. goto exit;
  676. }
  677. //
  678. // Get Aec Source and Capture Sink pins.
  679. //
  680. pListItem = lstConnectNodeInstance.GetListLast();
  681. pBottomConnection = lstConnectNodeInstance.GetListData(pListItem);
  682. FOR_EACH_LIST_ITEM_BACKWARD(&lstConnectNodeInstance, pConnectNodeInstance) {
  683. if (pConnectNodeInstance->pConnectNode->pPinNodeSource->
  684. pPinInfo->pFilterNode->GetType() & FILTER_TYPE_AEC) {
  685. pAecConnection = pConnectNodeInstance;
  686. break;
  687. }
  688. } END_EACH_LIST_ITEM
  689. if (NULL == pAecConnection || NULL == pBottomConnection) {
  690. DPF(5, "CSNI::AecConnectionFormat: Cannot find Aec or Capture");
  691. Status = STATUS_INVALID_DEVICE_REQUEST;
  692. goto exit;
  693. }
  694. DPF3(20, "Aec : %X %d %s",
  695. pAecConnection,
  696. pAecConnection->pConnectNode->pPinNodeSource->pPinInfo->PinId,
  697. pAecConnection->pConnectNode->pPinNodeSource->pPinInfo->pFilterNode->DumpName());
  698. DPF3(20, "Capture : %X %d %s",
  699. pBottomConnection,
  700. pBottomConnection->pConnectNode->pPinNodeSink->pPinInfo->PinId,
  701. pBottomConnection->pConnectNode->pPinNodeSink->pPinInfo->pFilterNode->DumpName());
  702. //
  703. // Find the intersection between kmixer source and capture sink.
  704. //
  705. Status = CreatePinIntersection(
  706. ppPinConnect,
  707. pBottomConnection->pConnectNode->pPinNodeSink,
  708. pAecConnection->pConnectNode->pPinNodeSource,
  709. pBottomConnection->pFilterNodeInstanceSink,
  710. pAecConnection->pFilterNodeInstanceSource);
  711. if(!NT_SUCCESS(Status)) {
  712. DPF(5, "CSNI::AecConnectionFormat: No intersection found");
  713. Status = STATUS_INVALID_DEVICE_REQUEST;
  714. goto exit;
  715. }
  716. #ifdef DEBUG
  717. DumpDataFormat(20, (PKSDATAFORMAT) (*ppPinConnect + 1));
  718. #endif
  719. exit:
  720. if(!NT_SUCCESS(Status)) {
  721. DPF2(90, "CSNI::AecConnectionFormat: %08x FAIL %08x", this, Status);
  722. delete [] *ppPinConnect;
  723. *ppPinConnect = NULL;
  724. }
  725. CleanUp();
  726. return(Status);
  727. } // AecConnectionFormat
  728. NTSTATUS
  729. CStartNodeInstance::Connect(
  730. PDEVICE_NODE pDeviceNode,
  731. PKSPIN_CONNECT pPinConnect,
  732. PWAVEFORMATEX pWaveFormatEx,
  733. PKSPIN_CONNECT pPinConnectDirect
  734. )
  735. {
  736. PCONNECT_NODE_INSTANCE pConnectNodeInstance;
  737. NTSTATUS Status = STATUS_SUCCESS;
  738. Status = CConnectNodeInstance::Create(this, pDeviceNode);
  739. if(!NT_SUCCESS(Status)) {
  740. goto exit;
  741. }
  742. //
  743. // Do all the bottom up connecting
  744. //
  745. FOR_EACH_LIST_ITEM_BACKWARD(&lstConnectNodeInstance, pConnectNodeInstance) {
  746. if(!pConnectNodeInstance->IsTopDown()) {
  747. //
  748. // For Aec sink pin do intersection, no matter what the format is.
  749. //
  750. if (pConnectNodeInstance->pFilterNodeInstanceSink->
  751. pFilterNode->GetType() & FILTER_TYPE_AEC) {
  752. Status = pConnectNodeInstance->Connect(NULL, NULL);
  753. }
  754. else {
  755. Status = pConnectNodeInstance->Connect(
  756. pWaveFormatEx,
  757. pPinConnectDirect);
  758. }
  759. if(!NT_SUCCESS(Status)) {
  760. goto exit;
  761. }
  762. }
  763. } END_EACH_LIST_ITEM
  764. pPinConnect->PinToHandle = NULL;
  765. Status = CPinNodeInstance::Create(
  766. &pPinNodeInstance,
  767. pFilterNodeInstance,
  768. pStartNode->pPinNode,
  769. pPinConnect,
  770. (pStartNode->fRender)
  771. #ifdef FIX_SOUND_LEAK
  772. ,lstConnectNodeInstance.IsLstEmpty()
  773. #endif
  774. );
  775. if(!NT_SUCCESS(Status)) {
  776. goto exit;
  777. }
  778. //
  779. // Do all the top down connecting
  780. //
  781. FOR_EACH_LIST_ITEM(&lstConnectNodeInstance, pConnectNodeInstance) {
  782. if(pConnectNodeInstance->IsTopDown()) {
  783. //
  784. // Rely on DataIntersection for all Topdown connections
  785. //
  786. Status = pConnectNodeInstance->Connect(NULL, NULL);
  787. if(!NT_SUCCESS(Status)) {
  788. goto exit;
  789. }
  790. }
  791. } END_EACH_LIST_ITEM
  792. DPF1(90, "CSNI::Connect: %08x SUCCESS", this);
  793. exit:
  794. if(!NT_SUCCESS(Status)) {
  795. DPF2(90, "CSNI::Connect: %08x FAIL %08x", this, Status);
  796. CleanUp();
  797. }
  798. return(Status);
  799. }
  800. //=============================================================================
  801. // Create an array which holds FileObject of the pin for each topology node
  802. // in this graph.
  803. // This array is later used as a lookup table for node communication.
  804. //
  805. NTSTATUS
  806. CStartNodeInstance::CreateTopologyTable(
  807. PGRAPH_NODE_INSTANCE pGraphNodeInstance
  808. )
  809. {
  810. PCONNECT_NODE_INSTANCE pConnectNodeInstance;
  811. NTSTATUS Status = STATUS_SUCCESS;
  812. PFILTER_NODE pFilterNode = NULL;
  813. ULONG n;
  814. Assert(this);
  815. Assert(pGraphNodeInstance);
  816. if(pGraphNodeInstance->Topology.TopologyNodesCount != 0) {
  817. ASSERT(papFileObjectTopologyTable == NULL);
  818. papFileObjectTopologyTable =
  819. new PFILE_OBJECT[pGraphNodeInstance->Topology.TopologyNodesCount];
  820. if(papFileObjectTopologyTable == NULL) {
  821. Status = STATUS_INSUFFICIENT_RESOURCES;
  822. goto exit;
  823. }
  824. }
  825. for(n = 0; n < pGraphNodeInstance->Topology.TopologyNodesCount; n++) {
  826. // if filter node is the same as last time, no need to search
  827. if(pFilterNode == pGraphNodeInstance->papTopologyNode[n]->pFilterNode) {
  828. ASSERT(n != 0);
  829. ASSERT(pFilterNode != NULL);
  830. papFileObjectTopologyTable[n] = papFileObjectTopologyTable[n - 1];
  831. continue;
  832. }
  833. pFilterNode = pGraphNodeInstance->papTopologyNode[n]->pFilterNode;
  834. Assert(pFilterNode);
  835. //
  836. // Now find a filter instance and a pin instance in this graph
  837. // instance for this filter node.
  838. //
  839. Assert(pPinNodeInstance);
  840. if(pPinNodeInstance->pPinNode->pPinInfo->pFilterNode == pFilterNode) {
  841. papFileObjectTopologyTable[n] = pPinNodeInstance->pFileObject;
  842. continue;
  843. }
  844. FOR_EACH_LIST_ITEM_BACKWARD( // Top Down
  845. &lstConnectNodeInstance,
  846. pConnectNodeInstance) {
  847. Assert(pConnectNodeInstance);
  848. Assert(pConnectNodeInstance->pPinNodeInstanceSink);
  849. Assert(pConnectNodeInstance->pPinNodeInstanceSink->pPinNode);
  850. Assert(
  851. pConnectNodeInstance->pPinNodeInstanceSink->pPinNode->pPinInfo);
  852. //
  853. // Use the sink pin handle for now. This should be fine until
  854. // Sysaudio supports a spliter.
  855. //
  856. if(pConnectNodeInstance->pPinNodeInstanceSink->
  857. pPinNode->pPinInfo->pFilterNode == pFilterNode) {
  858. papFileObjectTopologyTable[n] =
  859. pConnectNodeInstance->pPinNodeInstanceSink->pFileObject;
  860. break;
  861. }
  862. } END_EACH_LIST_ITEM
  863. }
  864. DPF1(90, "CreatePinInstanceTopologyTable PI: %08x",
  865. papFileObjectTopologyTable);
  866. exit:
  867. return(Status);
  868. }
  869. NTSTATUS
  870. CStartNodeInstance::GetTopologyNodeFileObject(
  871. OUT PFILE_OBJECT *ppFileObject,
  872. IN ULONG NodeId
  873. )
  874. {
  875. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  876. NTSTATUS Status = STATUS_SUCCESS;
  877. if(this == NULL) {
  878. Status = STATUS_NO_SUCH_DEVICE;
  879. goto exit;
  880. }
  881. Assert(this);
  882. ASSERT(pPinInstance != NULL);
  883. Status = pPinInstance->pFilterInstance->GetGraphNodeInstance(
  884. &pGraphNodeInstance);
  885. if(!NT_SUCCESS(Status)) {
  886. goto exit;
  887. }
  888. Assert(pGraphNodeInstance);
  889. if(NodeId >= pGraphNodeInstance->cTopologyNodes) {
  890. Trap();
  891. Status = STATUS_INVALID_DEVICE_REQUEST;
  892. goto exit;
  893. }
  894. if(papFileObjectTopologyTable == NULL ||
  895. papFileObjectTopologyTable[NodeId] == NULL) {
  896. Status = pGraphNodeInstance->GetTopologyNodeFileObject(
  897. ppFileObject,
  898. NodeId);
  899. if(!NT_SUCCESS(Status)) {
  900. goto exit;
  901. }
  902. }
  903. else {
  904. *ppFileObject = papFileObjectTopologyTable[NodeId];
  905. }
  906. exit:
  907. return(Status);
  908. }
  909. //---------------------------------------------------------------------------
  910. NTSTATUS
  911. CStartNodeInstance::SetState(
  912. KSSTATE NewState,
  913. ULONG ulFlags
  914. )
  915. {
  916. NTSTATUS Status = STATUS_SUCCESS;
  917. LONG State;
  918. //
  919. // ISSUE: 04/23/2002 ALPERS
  920. // Until we have the parameter validation layer, this function
  921. // is unprotected.
  922. //
  923. Assert(this);
  924. if(CurrentState == NewState) {
  925. ASSERT(NT_SUCCESS(Status));
  926. goto exit;
  927. }
  928. if(CurrentState < NewState) {
  929. for(State = CurrentState + 1; State <= NewState; State++) {
  930. Status = SetStateTopDown(
  931. (KSSTATE)State,
  932. CurrentState,
  933. ulFlags | SETSTATE_FLAG_SINK | SETSTATE_FLAG_SOURCE);
  934. if(!NT_SUCCESS(Status)) {
  935. goto exit;
  936. }
  937. CurrentState = (KSSTATE)State;
  938. }
  939. }
  940. else {
  941. for(State = CurrentState - 1; State >= NewState; State--) {
  942. Status = SetStateBottomUp(
  943. (KSSTATE)State,
  944. CurrentState,
  945. ulFlags | SETSTATE_FLAG_SINK | SETSTATE_FLAG_SOURCE);
  946. if(!NT_SUCCESS(Status)) {
  947. goto exit;
  948. }
  949. CurrentState = (KSSTATE)State;
  950. }
  951. }
  952. ASSERT(CurrentState == NewState);
  953. exit:
  954. return(Status);
  955. }
  956. NTSTATUS
  957. CStartNodeInstance::SetStateTopDown(
  958. KSSTATE NewState,
  959. KSSTATE PreviousState,
  960. ULONG ulFlags
  961. )
  962. {
  963. PCONNECT_NODE_INSTANCE pConnectNodeInstance;
  964. NTSTATUS Status = STATUS_SUCCESS;
  965. if(this != NULL) {
  966. Assert(this);
  967. if(ulFlags & SETSTATE_FLAG_SINK) {
  968. Status = pPinNodeInstance->SetState(
  969. NewState,
  970. PreviousState,
  971. ulFlags);
  972. if(!NT_SUCCESS(Status)) {
  973. goto exit;
  974. }
  975. }
  976. FOR_EACH_LIST_ITEM(
  977. &lstConnectNodeInstance,
  978. pConnectNodeInstance) {
  979. Status = pConnectNodeInstance->SetStateTopDown(
  980. NewState,
  981. PreviousState,
  982. ulFlags);
  983. if(!NT_SUCCESS(Status)) {
  984. goto exit;
  985. }
  986. } END_EACH_LIST_ITEM
  987. }
  988. exit:
  989. return(Status);
  990. }
  991. NTSTATUS
  992. CStartNodeInstance::SetStateBottomUp(
  993. KSSTATE NewState,
  994. KSSTATE PreviousState,
  995. ULONG ulFlags
  996. )
  997. {
  998. PCONNECT_NODE_INSTANCE pConnectNodeInstance;
  999. NTSTATUS Status = STATUS_SUCCESS;
  1000. if(this != NULL) {
  1001. Assert(this);
  1002. FOR_EACH_LIST_ITEM_BACKWARD(
  1003. &lstConnectNodeInstance,
  1004. pConnectNodeInstance) {
  1005. Status = pConnectNodeInstance->SetStateBottomUp(
  1006. NewState,
  1007. PreviousState,
  1008. ulFlags);
  1009. if(!NT_SUCCESS(Status)) {
  1010. goto exit;
  1011. }
  1012. } END_EACH_LIST_ITEM
  1013. if(ulFlags & SETSTATE_FLAG_SINK) {
  1014. Status = pPinNodeInstance->SetState(
  1015. NewState,
  1016. PreviousState,
  1017. ulFlags);
  1018. if(!NT_SUCCESS(Status)) {
  1019. goto exit;
  1020. }
  1021. }
  1022. }
  1023. exit:
  1024. return(Status);
  1025. }