|
|
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.