|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1992 Microsoft Corporation
4:
5: Module Name:
6:
7: volume.c
8:
9: Abstract:
10:
11: This module contains code for set and get volume IOCTLs
12:
13: Author:
14:
15: Robin Speed (RobinSp) 21-Oct-1992
16:
17: Environment:
18:
19: Kernel mode
20:
21: Revision History:
22:
23: --*/
24:
25: #include <string.h>
26: #include <soundlib.h> // Definition of what's in here
27:
28: //
29: // Internal routines
30: //
31:
32: VOID
33: SoundVolumeNotify(
34: IN OUT PLOCAL_DEVICE_INFO pLDI
35: );
36:
37: //
38: // Return the current volume setting. If the card doesn't support
39: // volume setting return maximum volume (FFFFFFFF)
40: //
41:
42: NTSTATUS
43: SoundIoctlGetVolume(
44: IN PLOCAL_DEVICE_INFO pLDI,
45: IN PIRP pIrp,
46: IN PIO_STACK_LOCATION IrpStack
47: )
48: {
49: PWAVE_DD_VOLUME pVol;
50:
51: if (pLDI->CreationFlags & SOUND_CREATION_NO_VOLUME) {
52: return STATUS_NOT_SUPPORTED;
53: }
54:
55: if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(WAVE_DD_VOLUME)) {
56: dprintf1(("Supplied buffer to small for requested data"));
57: return STATUS_BUFFER_TOO_SMALL;
58: }
59:
60:
61: //
62: // say how much we're sending back
63: //
64:
65: pIrp->IoStatus.Information = sizeof(WAVE_DD_VOLUME);
66:
67: //
68: // cast the buffer address to the pointer type we want
69: //
70:
71: pVol = (PWAVE_DD_VOLUME)pIrp->AssociatedIrp.SystemBuffer;
72:
73: //
74: // fill in the info
75: //
76:
77: *pVol = pLDI->Volume;
78:
79: return STATUS_SUCCESS;
80: }
81: //
82: // Set the volume
83: //
84:
85: NTSTATUS
86: SoundIoctlSetVolume(
87: IN PLOCAL_DEVICE_INFO pLDI,
88: IN PIRP pIrp,
89: IN PIO_STACK_LOCATION IrpStack
90: )
91: {
92: PWAVE_DD_VOLUME pVol;
93:
94: //
95: // See if volume setting is supported
96: //
97:
98: if (pLDI->CreationFlags & SOUND_CREATION_NO_VOLUME) {
99: return STATUS_NOT_SUPPORTED;
100: }
101:
102: if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WAVE_DD_VOLUME)) {
103: dprintf1(("Supplied buffer to small for requested data"));
104: return STATUS_BUFFER_TOO_SMALL;
105: }
106:
107: //
108: // cast the buffer address to the pointer type we want
109: //
110:
111: pVol = (PWAVE_DD_VOLUME)pIrp->AssociatedIrp.SystemBuffer;
112:
113: //
114: // If the device is 'open' or aux (which is not explicitly opened to
115: // play) and the volume has changed then actually set the volume.
116: //
117:
118: if (// (pLDI->DeviceType == AUX_DEVICE || *pLDI->DeviceBusy) &&
119: (pLDI->Volume.Left != pVol->Left ||
120: pLDI->Volume.Right != pVol->Right)) {
121:
122: //
123: // Set the volume in the device
124: //
125:
126: pLDI->Volume = *pVol;
127:
128: //
129: // say how much we're sending back
130: //
131:
132: pIrp->IoStatus.Information = sizeof(WAVE_DD_VOLUME);
133:
134: //
135: // Not all devices have volume setting routines. The 'real'
136: // device may in fact be sitting in user mode waiting for a
137: // volume change to complete
138: //
139:
140: (*pLDI->DeviceInit->HwSetVolume)(pLDI);
141:
142: #ifdef VOLUME_NOTIFY
143: //
144: // Tell anyone who's waiting for it to change
145: //
146:
147: SoundVolumeNotify(pLDI);
148: #endif // VOLUME_NOTIFY
149:
150: pLDI->VolumeChanged = TRUE;
151: }
152:
153: return STATUS_SUCCESS;
154: }
155:
156: #ifdef VOLUME_NOTIFY
157:
158:
159: NTSTATUS
160: SoundIoctlGetChangedVolume(
161: IN OUT PLOCAL_DEVICE_INFO pLDI,
162: IN PIRP pIrp,
163: IN PIO_STACK_LOCATION IrpStack
164: )
165: /*++
166:
167: Routine Description:
168:
169: Checks the parameters and limits waiters (arbitrarily) to 8.
170: Tests if the current volume is the same as that passed in. If
171: not then return the new volume immediately. If the volume has
172: not changed then put the Irp in the waiting list.
173:
174: Arguments:
175:
176: pLDI - Local device info
177: pIrp - Pointer to IO request packet
178: IrpStack - stack location info
179:
180: Return Value:
181:
182: STATUS_BUFFER_TOO_SMALL - sizes passed in too small
183: STATUS_INSUFFICIENT_RESOURCES - if too many people are trying to wait
184: STATUS_SUCCESS - if volume has changed
185: STATUS_PENDING - if volume was same as before.
186:
187: --*/
188: {
189: PWAVE_DD_VOLUME pVol;
190: pVol = (PWAVE_DD_VOLUME)pIrp->AssociatedIrp.SystemBuffer;
191:
192: //
193: // Check input parameters
194: //
195:
196: if (pLDI->CreationFlags & SOUND_CREATION_NO_VOLUME) {
197: return STATUS_NOT_SUPPORTED;
198: }
199:
200: if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
201: sizeof(AUX_DD_VOLUME) ||
202: IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
203: sizeof(AUX_DD_VOLUME)) {
204: return STATUS_BUFFER_TOO_SMALL;
205: }
206:
207: //
208: // See if we can complete it now - ie if the device is 'playing'
209: // and the volume set is not what was passed in.
210: //
211:
212: if (// (pLDI->DeviceType == AUX_DEVICE || *pLDI->DeviceBusy) &&
213: (pVol->Left != pLDI->Volume.Left || pVol->Right != pLDI->Volume.Right))
214: {
215: *pVol = pLDI->Volume;
216:
217: pIrp->IoStatus.Information = sizeof(*pVol);
218:
219: return STATUS_SUCCESS;
220: } else {
221:
222: IoMarkIrpPending(pIrp);
223: pIrp->IoStatus.Status = STATUS_PENDING;
224:
225: SoundAddIrpToCancellableQ(&pLDI->VolumeQueue, pIrp, FALSE);
226:
227: return STATUS_PENDING;
228: }
229:
230: }
231:
232:
233: VOID
234: SoundVolumeNotify(
235: IN OUT PLOCAL_DEVICE_INFO pLDI
236: )
237: /*++
238:
239: Routine Description:
240:
241: Notify all waiters on this device that the volume has changed.
242: This involves just copying the data into their Irps and
243: completing them.
244:
245: Arguments:
246:
247: pLDI - Local device info
248:
249: Return Value:
250:
251: None
252:
253: --*/
254: {
255: PLIST_ENTRY ListHead;
256: ListHead = &pLDI->VolumeQueue;
257:
258: //
259: // Remove all the queue entries, completing all
260: // the Irps represented by the entries
261: //
262:
263: for (;;) {
264: PIRP pIrp;
265:
266: pIrp = SoundRemoveFromCancellableQ(ListHead);
267:
268: if (pIrp == NULL) {
269: break;
270: }
271: *((PWAVE_DD_VOLUME)pIrp->AssociatedIrp.SystemBuffer) =
272: pLDI->Volume;
273:
274: pIrp->IoStatus.Status = STATUS_SUCCESS;
275: pIrp->IoStatus.Information = sizeof(WAVE_DD_VOLUME);
276:
277: //
278: // Bump priority here because the application may still be trying
279: // to be real-time
280: //
281: IoCompleteRequest(pIrp, IO_SOUND_INCREMENT);
282: }
283: }
284:
285:
286: #endif // VOLUME_NOTIFY
287:
288: //
289: // Default hardware volume setting routine - does nothing
290: //
291:
292: VOID
293: SoundNoVolume(
294: PLOCAL_DEVICE_INFO pLDI
295: )
296: {
297: return;
298: }
299:
300: VOID
301: SoundSaveDeviceVolume(
302: PLOCAL_DEVICE_INFO pLDI,
303: PWSTR KeyName
304: )
305: {
306: if (pLDI->VolumeChanged) {
307:
308: dprintf3(("Saving volume setting for device type %4.4s : %8X, %8X",
309: &pLDI->Key, pLDI->Volume.Left, pLDI->Volume.Right));
310:
311: SoundWriteRegistryDWORD(KeyName,
312: pLDI->DeviceInit->LeftVolumeName,
313: pLDI->Volume.Left);
314: SoundWriteRegistryDWORD(KeyName,
315: pLDI->DeviceInit->RightVolumeName,
316: pLDI->Volume.Right);
317: pLDI->VolumeChanged = FALSE;
318: }
319: }
320:
321:
322: #if 0
323: //
324: // Pitch is always 1.0 as the card does not support pitch shift
325: //
326:
327: NTSTATUS SoundIoctlGetPitch(PLOCAL_DEVICE_INFO pLDI, PIRP pIrp, PIO_STACK_LOCATION IrpStack)
328: {
329: PWAVE_DD_PITCH pPitch;
330:
331: if (pLDI->DeviceType != WAVE_OUT) {
332: return STATUS_INVALID_PARAMETER;
333: }
334:
335: if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(WAVE_DD_PITCH)) {
336: dprintf1(("Supplied buffer to small for requested data"));
337: return STATUS_BUFFER_TOO_SMALL;
338: }
339:
340: //
341: // say how much we're sending back
342: //
343:
344: pIrp->IoStatus.Information = sizeof(WAVE_DD_PITCH);
345:
346: //
347: // cast the buffer address to the pointer type we want
348: //
349:
350: pPitch = (PWAVE_DD_PITCH)pIrp->AssociatedIrp.SystemBuffer;
351:
352: //
353: // fill in the info
354: //
355:
356: pPitch->Pitch = 0x10000;
357:
358: return STATUS_SUCCESS;
359: }
360:
361: //
362: // Playback rate is always 1.0 as the card does not support rate shift
363: //
364:
365: NTSTATUS SoundIoctlGetPlaybackRate(PLOCAL_DEVICE_INFO pLDI, PIRP pIrp, PIO_STACK_LOCATION IrpStack)
366: {
367: PWAVE_DD_PLAYBACK_RATE pPlaybackRate;
368:
369: if (pLDI->DeviceType != WAVE_OUT) {
370: return STATUS_INVALID_PARAMETER;
371: }
372:
373: if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(WAVE_DD_PLAYBACK_RATE)) {
374: dprintf1(("Supplied buffer to small for requested data"));
375: return STATUS_BUFFER_TOO_SMALL;
376: }
377:
378: //
379: // say how much we're sending back
380: //
381:
382: pIrp->IoStatus.Information = sizeof(WAVE_DD_PLAYBACK_RATE);
383:
384: //
385: // cast the buffer address to the pointer type we want
386: //
387:
388: pPlaybackRate = (PWAVE_DD_PLAYBACK_RATE)pIrp->AssociatedIrp.SystemBuffer;
389:
390: //
391: // fill in the info
392: //
393:
394: pPlaybackRate->Rate = 0x10000;
395:
396: return STATUS_SUCCESS;
397: }
398:
399: #endif
400:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.