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.

941 lines
24 KiB

  1. // Copyright (c) 1998 Microsoft Corporation
  2. //
  3. // DirectMusic Software Synthesizer
  4. //
  5. #include "common.h"
  6. #include "private.h"
  7. #include "dmusicks.h"
  8. #define STR_MODULENAME "DmSynth: "
  9. #pragma code_seg("PAGE")
  10. // Property handlers
  11. //
  12. NTSTATUS PropertyHandler_SynthCaps(IN PPCPROPERTY_REQUEST);
  13. NTSTATUS PropertyHandler_SynthPortParameters(IN PPCPROPERTY_REQUEST);
  14. NTSTATUS PropertyHandler_SynthMasterClock(IN PPCPROPERTY_REQUEST);
  15. NTSTATUS PropertyHandler_SynthPortChannelGroups(IN PPCPROPERTY_REQUEST);
  16. NTSTATUS PropertyHandler_DlsDownload(IN PPCPROPERTY_REQUEST);
  17. NTSTATUS PropertyHandler_DlsUnload(IN PPCPROPERTY_REQUEST);
  18. NTSTATUS PropertyHandler_DlsCompact(IN PPCPROPERTY_REQUEST);
  19. NTSTATUS PropertyHandler_DlsAppend(IN PPCPROPERTY_REQUEST);
  20. NTSTATUS PropertyHandler_DlsVolume(IN PPCPROPERTY_REQUEST);
  21. NTSTATUS PropertyHandler_GetLatency(IN PPCPROPERTY_REQUEST);
  22. NTSTATUS PropertyHandler_GetLatencyClock(IN PPCPROPERTY_REQUEST);
  23. // CreateMiniportDirectMusic
  24. //
  25. //
  26. NTSTATUS CreateMiniportDmSynth
  27. (
  28. OUT PUNKNOWN * Unknown,
  29. IN PUNKNOWN UnknownOuter OPTIONAL,
  30. IN POOL_TYPE PoolType
  31. )
  32. {
  33. PAGED_CODE();
  34. ASSERT(Unknown);
  35. _DbgPrintF(DEBUGLVL_TERSE, ("Creating DirectMusic synth miniport"));
  36. STD_CREATE_BODY(CMiniportDmSynth, Unknown, UnknownOuter, PoolType);
  37. }
  38. STDMETHODIMP CMiniportDmSynth::NonDelegatingQueryInterface
  39. (
  40. IN REFIID Interface,
  41. OUT PVOID* Object
  42. )
  43. {
  44. PAGED_CODE();
  45. ASSERT(Object);
  46. if (IsEqualGUIDAligned(Interface, IID_IUnknown))
  47. {
  48. *Object = PVOID(PUNKNOWN(this));
  49. }
  50. else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
  51. {
  52. *Object = PVOID(PMINIPORT(this));
  53. }
  54. else if (IsEqualGUIDAligned(Interface, IID_IMiniportSynthesizer))
  55. {
  56. *Object = PVOID(PMINIPORTSYNTHESIZER(this));
  57. }
  58. else
  59. {
  60. *Object = NULL;
  61. }
  62. if (*Object)
  63. {
  64. PUNKNOWN(*Object)->AddRef();
  65. return STATUS_SUCCESS;
  66. }
  67. return STATUS_INVALID_PARAMETER;
  68. }
  69. CMiniportDmSynth::~CMiniportDmSynth()
  70. {
  71. }
  72. STDMETHODIMP CMiniportDmSynth::Init
  73. (
  74. IN PUNKNOWN Unknown OPTIONAL,
  75. IN PRESOURCELIST ResourceList,
  76. IN PPORTSYNTHESIZER Port_,
  77. OUT PSERVICEGROUP* ServiceGroup
  78. )
  79. {
  80. _DbgPrintF(DEBUGLVL_TERSE, ("[CMiniportDmSynth::Init]"));
  81. ASSERT(ResourceList);
  82. ASSERT(Port_);
  83. ASSERT(ServiceGroup);
  84. Port = Port_;
  85. Port->AddRef();
  86. Stream = NULL;
  87. *ServiceGroup = NULL;
  88. return STATUS_SUCCESS;
  89. }
  90. STDMETHODIMP CMiniportDmSynth::NewStream
  91. (
  92. OUT PMINIPORTSYNTHESIZERSTREAM * Stream_,
  93. IN PUNKNOWN OuterUnknown OPTIONAL,
  94. IN POOL_TYPE PoolType,
  95. IN ULONG Pin,
  96. IN BOOLEAN Capture,
  97. IN PKSDATAFORMAT DataFormat,
  98. OUT PSERVICEGROUP * ServiceGroup
  99. )
  100. {
  101. _DbgPrintF(DEBUGLVL_TERSE, ("[CMiniportDmSynth::NewStream]"));
  102. NTSTATUS nt = STATUS_SUCCESS;
  103. if (Stream)
  104. {
  105. // XXX Multiinstance!!!
  106. //
  107. nt = STATUS_INVALID_DEVICE_REQUEST;
  108. }
  109. else
  110. {
  111. CDmSynthStream *Stream = new(PoolType) CDmSynthStream(OuterUnknown);
  112. if (Stream)
  113. {
  114. nt = Stream->Init(this);
  115. if (NT_SUCCESS(nt))
  116. {
  117. Stream->AddRef();
  118. *Stream_ = PMINIPORTSYNTHESIZERSTREAM(Stream);
  119. }
  120. else
  121. {
  122. Stream->Release();
  123. Stream = NULL;
  124. }
  125. }
  126. else
  127. {
  128. nt = STATUS_INSUFFICIENT_RESOURCES;
  129. }
  130. }
  131. return nt;
  132. }
  133. STDMETHODIMP_(void) CMiniportDmSynth::Service()
  134. {
  135. }
  136. // ==============================================================================
  137. // PinDataRangesStream
  138. // Structures indicating range of valid format values for streaming pins.
  139. // ==============================================================================
  140. static
  141. KSDATARANGE_MUSIC PinDataRangesStream[] =
  142. {
  143. {
  144. {
  145. sizeof(KSDATARANGE_MUSIC),
  146. 0,
  147. 0,
  148. 0,
  149. STATICGUIDOF(KSDATAFORMAT_TYPE_MUSIC),
  150. STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DIRECTMUSIC),
  151. STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
  152. },
  153. STATICGUIDOF(KSMUSIC_TECHNOLOGY_WAVETABLE),
  154. 0, // Channels
  155. 0, // Notes
  156. 0x0000ffff // ChannelMask
  157. }
  158. };
  159. // ==============================================================================
  160. // PinDataRangePointersStream
  161. // List of pointers to structures indicating range of valid format values
  162. // for streaming pins.
  163. // ==============================================================================
  164. static
  165. PKSDATARANGE PinDataRangePointersStream[] =
  166. {
  167. PKSDATARANGE(&PinDataRangesStream[0])
  168. };
  169. #if 0
  170. // ==============================================================================
  171. // PinDataRangesBridge
  172. // Structures indicating range of valid format values for bridge pins.
  173. // ==============================================================================
  174. static
  175. KSDATARANGE PinDataRangesBridge[] =
  176. {
  177. {
  178. sizeof(KSDATARANGE),
  179. 0,
  180. 0,
  181. 0,
  182. STATICGUIDOF(KSDATAFORMAT_TYPE_MUSIC),
  183. STATICGUIDOF(KSDATAFORMAT_SUBTYPE_MIDI_BUS),
  184. STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
  185. }
  186. };
  187. // ==============================================================================
  188. // PinDataRangePointersBridge
  189. // List of pointers to structures indicating range of valid format values
  190. // for bridge pins.
  191. // ==============================================================================
  192. static
  193. PKSDATARANGE PinDataRangePointersBridge[] =
  194. {
  195. &PinDataRangesBridge[0]
  196. };
  197. #endif
  198. // ==============================================================================
  199. // PinDataRangesAudio
  200. // Structures indicating range of valid format values for audio pins.
  201. // ==============================================================================
  202. static
  203. KSDATARANGE_AUDIO PinDataRangesAudio[] =
  204. {
  205. {
  206. { sizeof(KSDATARANGE_AUDIO),
  207. 0,
  208. 0,
  209. 0,
  210. STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
  211. STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
  212. STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX),
  213. },
  214. 2,
  215. 16,
  216. 16,
  217. 22050,
  218. 22050
  219. }
  220. };
  221. // ==============================================================================
  222. // PinDataRangePointersAudio
  223. // List of pointers to structures indicating range of valid format values
  224. // for audio pins.
  225. // ==============================================================================
  226. static
  227. PKSDATARANGE PinDataRangePointersAudio[] =
  228. {
  229. (PKSDATARANGE)&PinDataRangesAudio
  230. };
  231. static
  232. PCPROPERTY_ITEM
  233. SynthProperties[] =
  234. {
  235. ///////////////////////////////////////////////////////////////////
  236. //
  237. // Configuration items
  238. //
  239. // Global: Synth caps
  240. //
  241. {
  242. &KSPROPSETID_Synth,
  243. KSPROPERTY_SYNTH_CAPS,
  244. KSPROPERTY_TYPE_GET,
  245. PropertyHandler_SynthCaps
  246. },
  247. // Per Stream: Synth port parameters
  248. //
  249. {
  250. &KSPROPSETID_Synth,
  251. KSPROPERTY_SYNTH_PORTPARAMETERS,
  252. KSPROPERTY_TYPE_GET,
  253. PropertyHandler_SynthPortParameters
  254. },
  255. // Global: Master clock
  256. //
  257. {
  258. &KSPROPSETID_Synth,
  259. KSPROPERTY_SYNTH_MASTERCLOCK,
  260. KSPROPERTY_TYPE_SET,
  261. PropertyHandler_SynthMasterClock
  262. },
  263. // Per Stream: Channel groups
  264. //
  265. {
  266. &KSPROPSETID_Synth,
  267. KSPROPERTY_SYNTH_CHANNELGROUPS,
  268. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
  269. PropertyHandler_SynthPortChannelGroups
  270. },
  271. ///////////////////////////////////////////////////////////////////
  272. //
  273. // DLS items
  274. //
  275. // Per stream: Download DLS sample
  276. //
  277. {
  278. &KSPROPSETID_Synth_Dls,
  279. KSPROPERTY_SYNTH_DOWNLOAD,
  280. KSPROPERTY_TYPE_GET,
  281. PropertyHandler_DlsDownload
  282. },
  283. // Per stream: Unload DLS sample
  284. //
  285. {
  286. &KSPROPSETID_Synth_Dls,
  287. KSPROPERTY_SYNTH_UNLOAD,
  288. KSPROPERTY_TYPE_SET,
  289. PropertyHandler_DlsUnload
  290. },
  291. // Global: Compact DLS memory
  292. //
  293. {
  294. &KSPROPSETID_Synth_Dls,
  295. KSPROPERTY_SYNTH_COMPACT,
  296. KSPROPERTY_TYPE_SET,
  297. PropertyHandler_DlsCompact
  298. },
  299. // Per stream: append
  300. //
  301. {
  302. &KSPROPSETID_Synth_Dls,
  303. KSPROPERTY_SYNTH_APPEND,
  304. KSPROPERTY_TYPE_SET,
  305. PropertyHandler_DlsAppend
  306. },
  307. // Per stream: volume
  308. //
  309. {
  310. &KSPROPSETID_Synth_Dls,
  311. KSPROPERTY_SYNTH_VOLUME,
  312. KSPROPERTY_TYPE_SET,
  313. PropertyHandler_DlsVolume
  314. },
  315. ///////////////////////////////////////////////////////////////////
  316. //
  317. // Clock items
  318. //
  319. // Per stream: Get desired latency
  320. //
  321. {
  322. &KSPROPSETID_Synth,
  323. KSPROPERTY_SYNTH_LATENCY,
  324. KSPROPERTY_TYPE_GET,
  325. PropertyHandler_GetLatency
  326. },
  327. // Per stream: Get current latency time
  328. //
  329. {
  330. &KSPROPSETID_Synth,
  331. KSPROPERTY_SYNTH_LatencyClock,
  332. KSPROPERTY_TYPE_GET,
  333. PropertyHandler_GetLatencyClock
  334. }
  335. };
  336. DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSynth, SynthProperties);
  337. // ==============================================================================
  338. // MiniportPins
  339. // List of pins.
  340. // ==============================================================================
  341. static
  342. PCPIN_DESCRIPTOR
  343. MiniportPins[] =
  344. {
  345. {
  346. 1,1,1, // InstanceCount
  347. NULL,
  348. { // KsPinDescriptor
  349. 0, // InterfacesCount
  350. NULL, // Interfaces
  351. 0, // MediumsCount
  352. NULL, // Mediums
  353. SIZEOF_ARRAY(PinDataRangePointersStream), // DataRangesCount
  354. PinDataRangePointersStream, // DataRanges
  355. KSPIN_DATAFLOW_IN, // DataFlow
  356. KSPIN_COMMUNICATION_SINK, // Communication
  357. (GUID *) &KSCATEGORY_AUDIO, // Category
  358. NULL, // Name
  359. 0 // Reserved
  360. }
  361. },
  362. #if 0
  363. {
  364. 0,0,0, // InstanceCount
  365. NULL, // AutomationTable
  366. { // KsPinDescriptor
  367. 0, // InterfacesCount
  368. NULL, // Interfaces
  369. 0, // MediumsCount
  370. NULL, // Mediums
  371. SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount
  372. PinDataRangePointersBridge, // DataRanges
  373. KSPIN_DATAFLOW_OUT, // DataFlow
  374. KSPIN_COMMUNICATION_NONE, // Communication
  375. (GUID *) &KSCATEGORY_AUDIO, // Category
  376. NULL, // Name
  377. 0 // Reserved
  378. }
  379. }
  380. #else
  381. {
  382. 1,1,1, // InstanceCount
  383. NULL, // AutomationTable
  384. { // KsPinDescriptor
  385. 0, // InterfacesCount
  386. NULL, // Interfaces
  387. 0, // MediumsCount
  388. NULL, // Mediums
  389. SIZEOF_ARRAY(PinDataRangePointersAudio), // DataRangesCount
  390. PinDataRangePointersAudio, // DataRanges
  391. KSPIN_DATAFLOW_OUT, // DataFlow
  392. KSPIN_COMMUNICATION_SOURCE, // Communication
  393. (GUID *) &KSCATEGORY_AUDIO, // Category
  394. NULL, // Name
  395. 0 // Reserved
  396. }
  397. }
  398. #endif
  399. };
  400. // ==============================================================================
  401. // MiniportNodes
  402. // List of nodes.
  403. // ==============================================================================
  404. #define CONST_PCNODE_DESCRIPTOR(n) { 0, NULL, &n, NULL }
  405. #define CONST_PCNODE_DESCRIPTOR_AUTO(n,a) { 0, &a, &n, NULL }
  406. static
  407. PCNODE_DESCRIPTOR MiniportNodes[] =
  408. {
  409. CONST_PCNODE_DESCRIPTOR_AUTO(KSNODETYPE_SYNTHESIZER, AutomationSynth)
  410. };
  411. // ==============================================================================
  412. // MiniportConnections
  413. // List of connections.
  414. // ==============================================================================
  415. static
  416. PCCONNECTION_DESCRIPTOR MiniportConnections[] =
  417. {
  418. // From node From pin To node To pin
  419. //
  420. { PCFILTER_NODE, 0, 0, 1 }, // Stream in to synth.
  421. { 0, 0, PCFILTER_NODE, 1 } // Synth to bridge out.
  422. };
  423. /*****************************************************************************
  424. * MiniportFilterDescriptor
  425. *****************************************************************************
  426. * Complete miniport description.
  427. */
  428. static
  429. PCFILTER_DESCRIPTOR
  430. MiniportFilterDescriptor =
  431. {
  432. 0, // Version
  433. NULL, // AutomationTable
  434. sizeof(PCPIN_DESCRIPTOR), // PinSize
  435. SIZEOF_ARRAY(MiniportPins), // PinCount
  436. MiniportPins, // Pins
  437. sizeof(PCNODE_DESCRIPTOR), // NodeSize
  438. SIZEOF_ARRAY(MiniportNodes), // NodeCount
  439. MiniportNodes, // Nodes
  440. SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
  441. MiniportConnections, // Connections
  442. 0, // CategoryCount
  443. NULL // Categories
  444. };
  445. STDMETHODIMP CMiniportDmSynth::GetDescription
  446. (
  447. OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
  448. )
  449. {
  450. PAGED_CODE();
  451. ASSERT(OutFilterDescriptor);
  452. _DbgPrintF(DEBUGLVL_VERBOSE, ("GetDescription"));
  453. *OutFilterDescriptor = &MiniportFilterDescriptor;
  454. return STATUS_SUCCESS;
  455. }
  456. STDMETHODIMP CMiniportDmSynth::DataRangeIntersection
  457. (
  458. IN ULONG PinId,
  459. IN PKSDATARANGE DataRange,
  460. IN PKSDATARANGE MatchingDataRange,
  461. IN ULONG OutputBufferLength,
  462. OUT PVOID ResultantFormat OPTIONAL,
  463. OUT PULONG ResultantFormatLength
  464. )
  465. {
  466. // XXX ???
  467. //
  468. return STATUS_SUCCESS;
  469. }
  470. ///////////////////////////////////////////////////////////////////////////////
  471. //
  472. // CDmSynthStream
  473. //
  474. CDmSynthStream::~CDmSynthStream()
  475. {
  476. _DbgPrintF(DEBUGLVL_TERSE, ("[CDmSynthStream destruct]"));
  477. if (Miniport)
  478. {
  479. Miniport->Stream = NULL;
  480. Miniport->Release();
  481. }
  482. if (Synth)
  483. {
  484. delete Synth;
  485. }
  486. if (Sink)
  487. {
  488. Sink->Release();
  489. }
  490. }
  491. NTSTATUS CDmSynthStream::Init
  492. (
  493. CMiniportDmSynth *Miniport_
  494. )
  495. {
  496. _DbgPrintF(DEBUGLVL_TERSE, ("[CDmSynthStream::Init]"));
  497. _DbgPrintF(DEBUGLVL_TERSE, ("Stream IUnkown is %08X", DWORD(PVOID(PUNKNOWN(this)))));
  498. Miniport = Miniport_;
  499. Miniport->AddRef();
  500. Synth = new CSynth;
  501. if (Synth == NULL)
  502. {
  503. Miniport->Release();
  504. return STATUS_NO_MEMORY;
  505. }
  506. Sink = new CSysLink;
  507. if (Sink == NULL)
  508. {
  509. delete Synth;
  510. Synth = NULL;
  511. Miniport->Release();
  512. return STATUS_NO_MEMORY;
  513. }
  514. return STATUS_SUCCESS;
  515. }
  516. STDMETHODIMP CDmSynthStream::NonDelegatingQueryInterface
  517. (
  518. IN REFIID Interface,
  519. OUT PVOID* Object
  520. )
  521. {
  522. PAGED_CODE();
  523. ASSERT(Object);
  524. if (IsEqualGUIDAligned(Interface, IID_IUnknown))
  525. {
  526. *Object = PVOID(PUNKNOWN(this));
  527. }
  528. else if (IsEqualGUIDAligned(Interface, IID_IMiniportSynthesizerStream))
  529. {
  530. *Object = PVOID(PMINIPORTSYNTHESIZERSTREAM(this));
  531. }
  532. else
  533. {
  534. *Object = NULL;
  535. }
  536. if (*Object)
  537. {
  538. //
  539. // We reference the interface for the caller.
  540. //
  541. PUNKNOWN(*Object)->AddRef();
  542. return STATUS_SUCCESS;
  543. }
  544. return STATUS_INVALID_PARAMETER;
  545. }
  546. STDMETHODIMP CDmSynthStream::SetState
  547. (
  548. IN KSSTATE NewState
  549. )
  550. {
  551. PAGED_CODE();
  552. _DbgPrintF(DEBUGLVL_VERBOSE, ("[CDmSynthStream::SetState]"));
  553. NTSTATUS nt = STATUS_SUCCESS;
  554. // XXX Propogate to activate state
  555. //
  556. switch (NewState)
  557. {
  558. case KSSTATE_RUN:
  559. nt = Synth->Activate(PortParams.SampleRate,
  560. PortParams.Stereo ? 2 : 1);
  561. break;
  562. case KSSTATE_ACQUIRE:
  563. case KSSTATE_STOP:
  564. case KSSTATE_PAUSE:
  565. nt = Synth->Deactivate();
  566. break;
  567. }
  568. return nt;
  569. }
  570. STDMETHODIMP CDmSynthStream::ConnectOutput
  571. (
  572. PMXFFILTER ConnectionPoint
  573. )
  574. {
  575. return STATUS_NOT_IMPLEMENTED;
  576. }
  577. STDMETHODIMP CDmSynthStream::DisconnectOutput
  578. (
  579. PMXFFILTER ConnectionPoint
  580. )
  581. {
  582. return STATUS_NOT_IMPLEMENTED;
  583. }
  584. STDMETHODIMP CDmSynthStream::PutMessage
  585. (
  586. IN PDMUS_KERNEL_EVENT Event
  587. )
  588. {
  589. PBYTE Data = (Event->ByteCount <= sizeof(PBYTE) ? &Event->ActualData.Data[0] : Event->ActualData.DataPtr);
  590. // This is just MIDI bytes
  591. //
  592. return Synth->PlayBuffer(Sink,
  593. Event->PresTime100Ns,
  594. Data,
  595. Event->ByteCount,
  596. (ULONG)Event->ChannelGroup);
  597. }
  598. // CDmSynthStream::HandlePortParams
  599. //
  600. // Fix up the port params to include defaults. Cache the params as well
  601. // as passing the updated version back.
  602. //
  603. STDMETHODIMP CDmSynthStream::HandlePortParams
  604. (
  605. IN PPCPROPERTY_REQUEST pRequest
  606. )
  607. {
  608. BOOL ValidParamChanged = FALSE;
  609. SYNTH_PORTPARAMS *Params = (SYNTH_PORTPARAMS*)pRequest->Value;
  610. if (pRequest->ValueSize < sizeof(SYNTH_PORTPARAMS))
  611. {
  612. return STATUS_BUFFER_TOO_SMALL;
  613. }
  614. if (!(Params->ValidParams & SYNTH_PORTPARAMS_VOICES))
  615. {
  616. Params->Voices = 32;
  617. }
  618. else if (Params->Voices > 32)
  619. {
  620. Params->Voices = 32;
  621. ValidParamChanged = TRUE;
  622. }
  623. if (!(Params->ValidParams & SYNTH_PORTPARAMS_CHANNELGROUPS))
  624. {
  625. Params->ChannelGroups = 32;
  626. }
  627. else if (Params->ChannelGroups > 32)
  628. {
  629. Params->ChannelGroups = 32;
  630. ValidParamChanged = TRUE;
  631. }
  632. if (!(Params->ValidParams & SYNTH_PORTPARAMS_SAMPLERATE))
  633. {
  634. Params->SampleRate = 22050;
  635. }
  636. else if (Params->SampleRate != 11025 && Params->SampleRate != 22050 && Params->SampleRate != 44100)
  637. {
  638. Params->SampleRate = 22050;
  639. ValidParamChanged = TRUE;
  640. }
  641. if (!(Params->ValidParams & SYNTH_PORTPARAMS_REVERB))
  642. {
  643. Params->Reverb = FALSE;
  644. }
  645. else if (Params->Reverb)
  646. {
  647. Params->Reverb = FALSE;
  648. ValidParamChanged = TRUE;
  649. }
  650. RtlCopyMemory(&PortParams, Params, sizeof(PortParams));
  651. return ValidParamChanged ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
  652. }
  653. ///////////////////////////////////////////////////////////////////////////////
  654. //
  655. // Property dispatchers
  656. //
  657. // XXX All of these need to be connected
  658. //
  659. NTSTATUS PropertyHandler_SynthCaps
  660. (
  661. IN PPCPROPERTY_REQUEST pRequest
  662. )
  663. {
  664. SYNTHCAPS caps;
  665. caps.Flags = SYNTH_PC_DLS | SYNTH_PC_SOFTWARESYNTH;
  666. caps.MemorySize = SYNTH_PC_SYSTEMMEMORY;
  667. caps.MaxChannelGroups = 32;
  668. caps.MaxVoices = 32;
  669. pRequest->ValueSize = min(pRequest->ValueSize, sizeof(caps));
  670. RtlCopyMemory(pRequest->Value, &caps, pRequest->ValueSize);
  671. return STATUS_SUCCESS;
  672. }
  673. // PropertyHandler_SynthPortParameters
  674. //
  675. NTSTATUS PropertyHandler_SynthPortParameters
  676. (
  677. IN PPCPROPERTY_REQUEST pRequest
  678. )
  679. {
  680. ASSERT(pRequest);
  681. ASSERT(pRequest->MinorTarget);
  682. return (PDMSYNTHSTREAM(pRequest->MinorTarget))->HandlePortParams(pRequest);
  683. }
  684. // PropertyHandler_SynthMasterClock
  685. //
  686. NTSTATUS PropertyHandler_SynthMasterClock
  687. (
  688. IN PPCPROPERTY_REQUEST pRequest
  689. )
  690. {
  691. return STATUS_SUCCESS;
  692. }
  693. // PropertyHandler_SynthPortChannelGroups
  694. //
  695. NTSTATUS PropertyHandler_SynthPortChannelGroups
  696. (
  697. IN PPCPROPERTY_REQUEST pRequest
  698. )
  699. {
  700. ASSERT(pRequest);
  701. ASSERT(pRequest->MinorTarget);
  702. if (pRequest->ValueSize < sizeof(ULONG))
  703. {
  704. return STATUS_BUFFER_TOO_SMALL;
  705. }
  706. ULONG ChannelGroups = *(PULONG)(pRequest->Value);
  707. return (PDMSYNTHSTREAM(pRequest->MinorTarget))->Synth->SetNumChannelGroups(ChannelGroups);
  708. }
  709. // PropertyHandler_DlsDownload
  710. //
  711. NTSTATUS PropertyHandler_DlsDownload
  712. (
  713. IN PPCPROPERTY_REQUEST pRequest
  714. )
  715. {
  716. // XXX Lock down this memory
  717. //
  718. // XXX Validate entire buffer size???
  719. //
  720. HANDLE DownloadHandle;
  721. BOOL Free;
  722. NTSTATUS Status = (PDMSYNTHSTREAM(pRequest->MinorTarget))->Synth->Download(
  723. &DownloadHandle,
  724. pRequest->Value,
  725. &Free);
  726. if (SUCCEEDED(Status))
  727. {
  728. ASSERT(pRequest->ValueSize >= sizeof(DownloadHandle));
  729. RtlCopyMemory(pRequest->Value, &DownloadHandle, sizeof(DownloadHandle));
  730. pRequest->ValueSize = sizeof(DownloadHandle);
  731. }
  732. return Status;
  733. }
  734. // PropertyHandler_DlsUnload
  735. //
  736. HRESULT CALLBACK UnloadComplete(HANDLE,HANDLE);
  737. NTSTATUS PropertyHandler_DlsUnload
  738. (
  739. IN PPCPROPERTY_REQUEST pRequest
  740. )
  741. {
  742. ASSERT(pRequest);
  743. ASSERT(pRequest->MinorTarget);
  744. if (pRequest->ValueSize < sizeof(HANDLE))
  745. {
  746. return STATUS_BUFFER_TOO_SMALL;
  747. }
  748. // XXX Need some concurrency control here
  749. //
  750. NTSTATUS Status = (PDMSYNTHSTREAM(pRequest->MinorTarget))->Synth->Unload(
  751. *(HANDLE*)pRequest->Value,
  752. UnloadComplete,
  753. (HANDLE)pRequest);
  754. return STATUS_SUCCESS;
  755. }
  756. HRESULT CALLBACK UnloadComplete(HANDLE WhichDownload, HANDLE CallbackInstance)
  757. {
  758. PPCPROPERTY_REQUEST pRequest = (PPCPROPERTY_REQUEST)CallbackInstance;
  759. PcCompletePendingPropertyRequest(pRequest, STATUS_SUCCESS);
  760. return STATUS_SUCCESS;
  761. }
  762. // PropertyHandler_DlsCompact
  763. //
  764. // We don't care
  765. //
  766. NTSTATUS PropertyHandler_DlsCompact
  767. (
  768. IN PPCPROPERTY_REQUEST pRequest
  769. )
  770. {
  771. return STATUS_SUCCESS;
  772. }
  773. NTSTATUS PropertyHandler_DlsAppend
  774. (
  775. IN PPCPROPERTY_REQUEST pRequest
  776. )
  777. {
  778. ASSERT(pRequest);
  779. if (pRequest->ValueSize < sizeof(ULONG))
  780. {
  781. return STATUS_BUFFER_TOO_SMALL;
  782. }
  783. *(PULONG)(pRequest->Value) = 4;
  784. pRequest->ValueSize = sizeof(ULONG);
  785. return STATUS_SUCCESS;
  786. }
  787. NTSTATUS PropertyHandler_DlsVolume
  788. (
  789. IN PPCPROPERTY_REQUEST pRequest
  790. )
  791. {
  792. // XXX *Both* versions of the synth need this
  793. //
  794. return STATUS_SUCCESS;
  795. }
  796. NTSTATUS PropertyHandler_GetLatency
  797. (
  798. IN PPCPROPERTY_REQUEST pRequest
  799. )
  800. {
  801. if (pRequest->ValueSize < sizeof(ULONGLONG))
  802. {
  803. return STATUS_BUFFER_TOO_SMALL;
  804. }
  805. *((PULONGLONG)pRequest->Value) = 0;
  806. pRequest->ValueSize = sizeof(ULONGLONG);
  807. return STATUS_SUCCESS;
  808. }
  809. NTSTATUS PropertyHandler_GetLatencyClock
  810. (
  811. IN PPCPROPERTY_REQUEST pRequest
  812. )
  813. {
  814. // XXX This depends on the synth sink
  815. //
  816. return STATUS_SUCCESS;
  817. }