cc3e5f24c93f094d6a0f6a35c23d9b4bb9034d56
[reactos.git] / sdk / lib / drivers / sound / mmixer / wave.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/wave.c
5 * PURPOSE: Wave Handling Functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "precomp.h"
10
11 #define YDEBUG
12 #include <debug.h>
13
14 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
16 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
17 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
18 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
19 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
20
21 typedef struct
22 {
23 ULONG SampleRate;
24 ULONG Bit8Mono;
25 ULONG Bit8Stereo;
26 ULONG Bit16Mono;
27 ULONG Bit16Stereo;
28 }AUDIO_RANGE;
29
30 #define AUDIO_TEST_RANGE (5)
31
32 static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] =
33 {
34 {
35 11025,
36 WAVE_FORMAT_1M08,
37 WAVE_FORMAT_1S08,
38 WAVE_FORMAT_1M16,
39 WAVE_FORMAT_1S16
40 },
41 {
42 22050,
43 WAVE_FORMAT_2M08,
44 WAVE_FORMAT_2S08,
45 WAVE_FORMAT_2M16,
46 WAVE_FORMAT_2S16
47 },
48 {
49 44100,
50 WAVE_FORMAT_4M08,
51 WAVE_FORMAT_4S08,
52 WAVE_FORMAT_4M16,
53 WAVE_FORMAT_4S16
54 },
55 {
56 48000,
57 WAVE_FORMAT_48M08,
58 WAVE_FORMAT_48S08,
59 WAVE_FORMAT_48M16,
60 WAVE_FORMAT_48S16
61 },
62 {
63 96000,
64 WAVE_FORMAT_96M08,
65 WAVE_FORMAT_96S08,
66 WAVE_FORMAT_96M16,
67 WAVE_FORMAT_96S16
68 }
69 };
70
71 PKSPIN_CONNECT
72 MMixerAllocatePinConnect(
73 IN PMIXER_CONTEXT MixerContext,
74 ULONG DataFormatSize)
75 {
76 return MixerContext->Alloc(sizeof(KSPIN_CONNECT) + DataFormatSize);
77 }
78
79 MIXER_STATUS
80 MMixerGetWaveInfoByIndexAndType(
81 IN PMIXER_LIST MixerList,
82 IN ULONG DeviceIndex,
83 IN ULONG bWaveInType,
84 OUT LPWAVE_INFO *OutWaveInfo)
85 {
86 ULONG Index = 0;
87 PLIST_ENTRY Entry, ListHead;
88 LPWAVE_INFO WaveInfo;
89
90 if (bWaveInType)
91 ListHead = &MixerList->WaveInList;
92 else
93 ListHead = &MixerList->WaveOutList;
94
95 /* get first entry */
96 Entry = ListHead->Flink;
97
98 while(Entry != ListHead)
99 {
100 WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry);
101
102 if (Index == DeviceIndex)
103 {
104 *OutWaveInfo = WaveInfo;
105 return MM_STATUS_SUCCESS;
106 }
107 Index++;
108 Entry = Entry->Flink;
109 }
110
111 return MM_STATUS_INVALID_PARAMETER;
112 }
113
114
115
116
117 VOID
118 MMixerInitializeDataFormat(
119 IN PKSDATAFORMAT_WAVEFORMATEX DataFormat,
120 LPWAVEFORMATEX WaveFormatEx)
121 {
122
123 DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
124 DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels;
125 DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
126 DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
127 DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
128 DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
129 DataFormat->WaveFormatEx.cbSize = 0;
130 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
131 DataFormat->DataFormat.Flags = 0;
132 DataFormat->DataFormat.Reserved = 0;
133 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
134
135 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
136 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
137 DataFormat->DataFormat.SampleSize = 4;
138 }
139
140
141 MIXER_STATUS
142 MMixerGetAudioPinDataRanges(
143 IN PMIXER_CONTEXT MixerContext,
144 IN HANDLE hDevice,
145 IN ULONG PinId,
146 IN OUT PKSMULTIPLE_ITEM * OutMultipleItem)
147 {
148 KSP_PIN PinProperty;
149 ULONG BytesReturned = 0;
150 MIXER_STATUS Status;
151 PKSMULTIPLE_ITEM MultipleItem;
152
153 /* retrieve size of data ranges buffer */
154 PinProperty.Reserved = 0;
155 PinProperty.PinId = PinId;
156 PinProperty.Property.Set = KSPROPSETID_Pin;
157 PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
158 PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
159
160 Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
161 if (Status != MM_STATUS_MORE_ENTRIES)
162 {
163 return Status;
164 }
165
166 MultipleItem = MixerContext->Alloc(BytesReturned);
167 if (!MultipleItem)
168 {
169 /* not enough memory */
170 return MM_STATUS_NO_MEMORY;
171 }
172
173 Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
174 if (Status != MM_STATUS_SUCCESS)
175 {
176 /* failed */
177 MixerContext->Free(MultipleItem);
178 return Status;
179 }
180
181 /* save result */
182 *OutMultipleItem = MultipleItem;
183 return Status;
184 }
185
186 MIXER_STATUS
187 MMixerFindAudioDataRange(
188 PKSMULTIPLE_ITEM MultipleItem,
189 PKSDATARANGE_AUDIO * OutDataRangeAudio)
190 {
191 ULONG Index;
192 PKSDATARANGE_AUDIO DataRangeAudio;
193 PKSDATARANGE DataRange;
194
195 DataRange = (PKSDATARANGE) (MultipleItem + 1);
196 for(Index = 0; Index < MultipleItem->Count; Index++)
197 {
198 if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO))
199 {
200 DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange;
201 if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
202 IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
203 IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
204 {
205 DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency,
206 DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels);
207 *OutDataRangeAudio = DataRangeAudio;
208 return MM_STATUS_SUCCESS;
209 }
210 }
211 DataRange = (PKSDATARANGE)((ULONG_PTR)DataRange + DataRange->FormatSize);
212 }
213 return MM_STATUS_UNSUCCESSFUL;
214 }
215
216 MIXER_STATUS
217 MMixerOpenWavePin(
218 IN PMIXER_CONTEXT MixerContext,
219 IN PMIXER_LIST MixerList,
220 IN ULONG DeviceId,
221 IN ULONG PinId,
222 IN LPWAVEFORMATEX WaveFormatEx,
223 IN ACCESS_MASK DesiredAccess,
224 IN PIN_CREATE_CALLBACK CreateCallback,
225 IN PVOID Context,
226 OUT PHANDLE PinHandle)
227 {
228 PKSPIN_CONNECT PinConnect;
229 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
230 LPMIXER_DATA MixerData;
231 NTSTATUS Status;
232 MIXER_STATUS MixerStatus;
233
234 MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
235 if (!MixerData)
236 return MM_STATUS_INVALID_PARAMETER;
237
238 /* allocate pin connect */
239 PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX));
240 if (!PinConnect)
241 {
242 /* no memory */
243 return MM_STATUS_NO_MEMORY;
244 }
245
246 /* initialize pin connect struct */
247 MMixerInitializePinConnect(PinConnect, PinId);
248
249 /* get offset to dataformat */
250 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1);
251 /* initialize with requested wave format */
252 MMixerInitializeDataFormat(DataFormat, WaveFormatEx);
253
254 if (CreateCallback)
255 {
256 /* let the callback handle the creation */
257 MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
258 }
259 else
260 {
261 /* now create the pin */
262 Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
263
264 /* normalize status */
265 if (Status == STATUS_SUCCESS)
266 MixerStatus = MM_STATUS_SUCCESS;
267 else
268 MixerStatus = MM_STATUS_UNSUCCESSFUL;
269 }
270
271 /* free create info */
272 MixerContext->Free(PinConnect);
273
274 /* done */
275 return MixerStatus;
276 }
277
278 VOID
279 MMixerCheckFormat(
280 IN PKSDATARANGE_AUDIO DataRangeAudio,
281 IN LPWAVE_INFO WaveInfo,
282 IN ULONG bInput)
283 {
284 ULONG Index, SampleFrequency;
285 ULONG Result = 0;
286
287 for(Index = 0; Index < AUDIO_TEST_RANGE; Index++)
288 {
289 SampleFrequency = TestRange[Index].SampleRate;
290
291 if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency)
292 {
293 /* the audio adapter supports the sample frequency */
294 if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8)
295 {
296 Result |= TestRange[Index].Bit8Mono;
297
298 if (DataRangeAudio->MaximumChannels > 1)
299 {
300 /* check if pin supports the sample rate in 8-Bit Stereo */
301 Result |= TestRange[Index].Bit8Stereo;
302 }
303 }
304
305 if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16)
306 {
307 /* check if pin supports the sample rate in 16-Bit Mono */
308 Result |= TestRange[Index].Bit16Mono;
309
310
311 if (DataRangeAudio->MaximumChannels > 1)
312 {
313 /* check if pin supports the sample rate in 16-Bit Stereo */
314 Result |= TestRange[Index].Bit16Stereo;
315 }
316 }
317 }
318 }
319
320
321 if (bInput)
322 WaveInfo->u.InCaps.dwFormats = Result;
323 else
324 WaveInfo->u.OutCaps.dwFormats = Result;
325
326 DPRINT("Format %lx bInput %u\n", Result, bInput);
327 }
328
329 MIXER_STATUS
330 MMixerInitializeWaveInfo(
331 IN PMIXER_CONTEXT MixerContext,
332 IN PMIXER_LIST MixerList,
333 IN LPMIXER_DATA MixerData,
334 IN LPWSTR DeviceName,
335 IN ULONG bWaveIn,
336 IN ULONG PinCount,
337 IN PULONG Pins)
338 {
339 MIXER_STATUS Status;
340 PKSMULTIPLE_ITEM MultipleItem;
341 PKSDATARANGE_AUDIO DataRangeAudio;
342 LPWAVE_INFO WaveInfo;
343
344 WaveInfo = (LPWAVE_INFO)MixerContext->Alloc(sizeof(WAVE_INFO));
345 if (!WaveInfo)
346 return MM_STATUS_NO_MEMORY;
347
348 if (PinCount > 1)
349 {
350 /* FIXME support multiple pins for wave device */
351 DPRINT1("Implement support for multiple pins\n");
352 //ASSERT(PinCount == 1);
353 }
354
355 /* initialize wave info */
356 WaveInfo->DeviceId = MixerData->DeviceId;
357 WaveInfo->PinId = Pins[0];
358
359 /* sanity check */
360 ASSERT(wcslen(DeviceName) + 1 < MAXPNAMELEN);
361
362 /* copy device name */
363 if (bWaveIn)
364 {
365 wcscpy(WaveInfo->u.InCaps.szPname, DeviceName);
366 }
367 else
368 {
369 wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName);
370 }
371
372 /* FIXME determine manufacturer / product id */
373 if (bWaveIn)
374 {
375 WaveInfo->u.InCaps.wMid = MM_MICROSOFT;
376 WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED;
377 WaveInfo->u.InCaps.vDriverVersion = 1;
378 }
379 else
380 {
381 WaveInfo->u.OutCaps.wMid = MM_MICROSOFT;
382 WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED;
383 WaveInfo->u.OutCaps.vDriverVersion = 1;
384 }
385
386 /* get audio pin data ranges */
387 Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Pins[0], &MultipleItem);
388 if (Status != MM_STATUS_SUCCESS)
389 {
390 /* failed to get audio pin data ranges */
391 MixerContext->Free(WaveInfo);
392 return MM_STATUS_UNSUCCESSFUL;
393 }
394
395 /* find an KSDATARANGE_AUDIO range */
396 Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio);
397 if (Status != MM_STATUS_SUCCESS)
398 {
399 /* failed to find audio pin data range */
400 MixerContext->Free(MultipleItem);
401 MixerContext->Free(WaveInfo);
402 return MM_STATUS_UNSUCCESSFUL;
403 }
404
405 /* store channel count */
406 if (bWaveIn)
407 {
408 WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels;
409 }
410 else
411 {
412 WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels;
413 }
414
415 /* get all supported formats */
416 MMixerCheckFormat(DataRangeAudio, WaveInfo, bWaveIn);
417
418 /* free dataranges buffer */
419 MixerContext->Free(MultipleItem);
420
421 if (bWaveIn)
422 {
423 InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry);
424 MixerList->WaveInListCount++;
425 }
426 else
427 {
428 InsertTailList(&MixerList->WaveOutList, &WaveInfo->Entry);
429 MixerList->WaveOutListCount++;
430 }
431
432 return MM_STATUS_SUCCESS;
433 }
434
435 MIXER_STATUS
436 MMixerOpenWave(
437 IN PMIXER_CONTEXT MixerContext,
438 IN ULONG DeviceIndex,
439 IN ULONG bWaveIn,
440 IN LPWAVEFORMATEX WaveFormat,
441 IN PIN_CREATE_CALLBACK CreateCallback,
442 IN PVOID Context,
443 OUT PHANDLE PinHandle)
444 {
445 PMIXER_LIST MixerList;
446 MIXER_STATUS Status;
447 LPWAVE_INFO WaveInfo;
448 ACCESS_MASK DesiredAccess = 0;
449
450 /* verify mixer context */
451 Status = MMixerVerifyContext(MixerContext);
452
453 if (Status != MM_STATUS_SUCCESS)
454 {
455 /* invalid context passed */
456 return Status;
457 }
458
459 /* grab mixer list */
460 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
461
462 if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM)
463 {
464 /* not implemented */
465 return MM_STATUS_NOT_IMPLEMENTED;
466 }
467
468 /* find destination wave */
469 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, bWaveIn, &WaveInfo);
470 if (Status != MM_STATUS_SUCCESS)
471 {
472 /* failed to find wave info */
473 return MM_STATUS_INVALID_PARAMETER;
474 }
475
476 /* get desired access */
477 if (bWaveIn)
478 {
479 DesiredAccess |= GENERIC_READ;
480 }
481 else
482 {
483 DesiredAccess |= GENERIC_WRITE;
484 }
485
486 /* now try open the pin */
487 return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, CreateCallback, Context, PinHandle);
488 }
489
490 MIXER_STATUS
491 MMixerWaveInCapabilities(
492 IN PMIXER_CONTEXT MixerContext,
493 IN ULONG DeviceIndex,
494 OUT LPWAVEINCAPSW Caps)
495 {
496 PMIXER_LIST MixerList;
497 MIXER_STATUS Status;
498 LPWAVE_INFO WaveInfo;
499
500 /* verify mixer context */
501 Status = MMixerVerifyContext(MixerContext);
502
503 if (Status != MM_STATUS_SUCCESS)
504 {
505 /* invalid context passed */
506 return Status;
507 }
508
509 /* grab mixer list */
510 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
511
512 /* find destination wave */
513 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, TRUE, &WaveInfo);
514 if (Status != MM_STATUS_SUCCESS)
515 {
516 /* failed to find wave info */
517 return MM_STATUS_UNSUCCESSFUL;
518 }
519
520 /* copy capabilities */
521 MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW));
522
523 return MM_STATUS_SUCCESS;
524 }
525
526 MIXER_STATUS
527 MMixerWaveOutCapabilities(
528 IN PMIXER_CONTEXT MixerContext,
529 IN ULONG DeviceIndex,
530 OUT LPWAVEOUTCAPSW Caps)
531 {
532 PMIXER_LIST MixerList;
533 MIXER_STATUS Status;
534 LPWAVE_INFO WaveInfo;
535
536 /* verify mixer context */
537 Status = MMixerVerifyContext(MixerContext);
538
539 if (Status != MM_STATUS_SUCCESS)
540 {
541 /* invalid context passed */
542 return Status;
543 }
544
545 /* grab mixer list */
546 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
547
548 /* find destination wave */
549 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, FALSE, &WaveInfo);
550 if (Status != MM_STATUS_SUCCESS)
551 {
552 /* failed to find wave info */
553 return MM_STATUS_UNSUCCESSFUL;
554 }
555
556 /* copy capabilities */
557 MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW));
558
559 return MM_STATUS_SUCCESS;
560 }
561
562 ULONG
563 MMixerGetWaveInCount(
564 IN PMIXER_CONTEXT MixerContext)
565 {
566 PMIXER_LIST MixerList;
567 MIXER_STATUS Status;
568
569 /* verify mixer context */
570 Status = MMixerVerifyContext(MixerContext);
571
572 if (Status != MM_STATUS_SUCCESS)
573 {
574 /* invalid context passed */
575 return Status;
576 }
577
578 /* grab mixer list */
579 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
580
581 return MixerList->WaveInListCount;
582 }
583
584 ULONG
585 MMixerGetWaveOutCount(
586 IN PMIXER_CONTEXT MixerContext)
587 {
588 PMIXER_LIST MixerList;
589 MIXER_STATUS Status;
590
591 /* verify mixer context */
592 Status = MMixerVerifyContext(MixerContext);
593
594 if (Status != MM_STATUS_SUCCESS)
595 {
596 /* invalid context passed */
597 return Status;
598 }
599
600 /* grab mixer list */
601 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
602
603 return MixerList->WaveOutListCount;
604 }
605
606 MIXER_STATUS
607 MMixerSetWaveStatus(
608 IN PMIXER_CONTEXT MixerContext,
609 IN HANDLE PinHandle,
610 IN KSSTATE State)
611 {
612 KSPROPERTY Property;
613 ULONG Length;
614 MIXER_STATUS Status;
615
616 /* verify mixer context */
617 Status = MMixerVerifyContext(MixerContext);
618
619 if (Status != MM_STATUS_SUCCESS)
620 {
621 /* invalid context passed */
622 return Status;
623 }
624
625 /* setup property request */
626 Property.Set = KSPROPSETID_Connection;
627 Property.Id = KSPROPERTY_CONNECTION_STATE;
628 Property.Flags = KSPROPERTY_TYPE_SET;
629
630 return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length);
631 }
632
633 MIXER_STATUS
634 MMixerSetWaveResetState(
635 IN PMIXER_CONTEXT MixerContext,
636 IN HANDLE PinHandle,
637 IN ULONG bBegin)
638 {
639 ULONG Length;
640 MIXER_STATUS Status;
641 KSRESET Reset;
642
643 /* verify mixer context */
644 Status = MMixerVerifyContext(MixerContext);
645
646 if (Status != MM_STATUS_SUCCESS)
647 {
648 /* invalid context passed */
649 return Status;
650 }
651
652 /* begin / stop reset */
653 Reset = (bBegin ? KSRESET_BEGIN : KSRESET_END);
654
655 return MixerContext->Control(PinHandle, IOCTL_KS_RESET_STATE, &Reset, sizeof(KSRESET), NULL, 0, &Length);
656 }
657
658 MIXER_STATUS
659 MMixerGetWaveDevicePath(
660 IN PMIXER_CONTEXT MixerContext,
661 IN ULONG bWaveIn,
662 IN ULONG DeviceId,
663 OUT LPWSTR * DevicePath)
664 {
665 PMIXER_LIST MixerList;
666 LPMIXER_DATA MixerData;
667 LPWAVE_INFO WaveInfo;
668 ULONG Length;
669 MIXER_STATUS Status;
670
671 /* verify mixer context */
672 Status = MMixerVerifyContext(MixerContext);
673
674 if (Status != MM_STATUS_SUCCESS)
675 {
676 /* invalid context passed */
677 return Status;
678 }
679
680 /* grab mixer list */
681 MixerList = (PMIXER_LIST)MixerContext->MixerContext;
682
683 /* find destination wave */
684 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceId, bWaveIn, &WaveInfo);
685 if (Status != MM_STATUS_SUCCESS)
686 {
687 /* failed to find wave info */
688 return MM_STATUS_INVALID_PARAMETER;
689 }
690
691 /* get associated device id */
692 MixerData = MMixerGetDataByDeviceId(MixerList, WaveInfo->DeviceId);
693 if (!MixerData)
694 return MM_STATUS_INVALID_PARAMETER;
695
696 /* calculate length */
697 Length = wcslen(MixerData->DeviceName)+1;
698
699 /* allocate destination buffer */
700 *DevicePath = MixerContext->Alloc(Length * sizeof(WCHAR));
701
702 if (!*DevicePath)
703 {
704 /* no memory */
705 return MM_STATUS_NO_MEMORY;
706 }
707
708 /* copy device path */
709 MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR));
710
711 /* done */
712 return MM_STATUS_SUCCESS;
713 }