Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmmixer.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Sound System 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: dll/win32/wdmaud.drv/mmixer.c 00005 * 00006 * PURPOSE: WDM Audio Mixer API (User-mode part) 00007 * PROGRAMMERS: Johannes Anderwald 00008 */ 00009 00010 #include "wdmaud.h" 00011 00012 typedef struct 00013 { 00014 KSSTREAM_HEADER Header; 00015 HANDLE hDevice; 00016 PSOUND_OVERLAPPED Overlap; 00017 LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine; 00018 DWORD IoCtl; 00019 }IO_PACKET, *LPIO_PACKET; 00020 00021 BOOL MMixerLibraryInitialized = FALSE; 00022 00023 00024 00025 PVOID Alloc(ULONG NumBytes); 00026 MIXER_STATUS Close(HANDLE hDevice); 00027 VOID Free(PVOID Block); 00028 VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); 00029 MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); 00030 MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); 00031 MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey); 00032 MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey); 00033 MIXER_STATUS CloseKey(IN HANDLE hKey); 00034 MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType); 00035 PVOID AllocEventData(IN ULONG ExtraSize); 00036 VOID FreeEventData(IN PVOID EventData); 00037 00038 MIXER_CONTEXT MixerContext = 00039 { 00040 sizeof(MIXER_CONTEXT), 00041 NULL, 00042 Alloc, 00043 Control, 00044 Free, 00045 Open, 00046 Close, 00047 Copy, 00048 OpenKey, 00049 QueryKeyValue, 00050 CloseKey, 00051 AllocEventData, 00052 FreeEventData 00053 }; 00054 00055 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; 00056 00057 MIXER_STATUS 00058 QueryKeyValue( 00059 IN HANDLE hKey, 00060 IN LPWSTR KeyName, 00061 OUT PVOID * ResultBuffer, 00062 OUT PULONG ResultLength, 00063 OUT PULONG KeyType) 00064 { 00065 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND) 00066 return MM_STATUS_UNSUCCESSFUL; 00067 00068 *ResultBuffer = HeapAlloc(GetProcessHeap(), 0, *ResultLength); 00069 if (*ResultBuffer == NULL) 00070 return MM_STATUS_NO_MEMORY; 00071 00072 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, *ResultBuffer, ResultLength) != ERROR_SUCCESS) 00073 { 00074 HeapFree(GetProcessHeap(), 0, *ResultBuffer); 00075 return MM_STATUS_UNSUCCESSFUL; 00076 } 00077 return MM_STATUS_SUCCESS; 00078 } 00079 00080 MIXER_STATUS 00081 OpenKey( 00082 IN HANDLE hKey, 00083 IN LPWSTR SubKey, 00084 IN ULONG DesiredAccess, 00085 OUT PHANDLE OutKey) 00086 { 00087 if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS) 00088 return MM_STATUS_SUCCESS; 00089 00090 return MM_STATUS_UNSUCCESSFUL; 00091 } 00092 00093 MIXER_STATUS 00094 CloseKey( 00095 IN HANDLE hKey) 00096 { 00097 RegCloseKey((HKEY)hKey); 00098 return MM_STATUS_SUCCESS; 00099 } 00100 00101 00102 PVOID Alloc(ULONG NumBytes) 00103 { 00104 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes); 00105 } 00106 00107 MIXER_STATUS 00108 Close(HANDLE hDevice) 00109 { 00110 if (CloseHandle(hDevice)) 00111 return MM_STATUS_SUCCESS; 00112 else 00113 return MM_STATUS_UNSUCCESSFUL; 00114 } 00115 00116 VOID 00117 Free(PVOID Block) 00118 { 00119 HeapFree(GetProcessHeap(), 0, Block); 00120 } 00121 00122 VOID 00123 Copy(PVOID Src, PVOID Dst, ULONG NumBytes) 00124 { 00125 RtlMoveMemory(Src, Dst, NumBytes); 00126 } 00127 00128 MIXER_STATUS 00129 Open( 00130 IN LPWSTR DevicePath, 00131 OUT PHANDLE hDevice) 00132 { 00133 DevicePath[1] = L'\\'; 00134 *hDevice = CreateFileW(DevicePath, 00135 GENERIC_READ | GENERIC_WRITE, 00136 0, 00137 NULL, 00138 OPEN_EXISTING, 00139 FILE_FLAG_OVERLAPPED, 00140 NULL); 00141 if (*hDevice == INVALID_HANDLE_VALUE) 00142 { 00143 return MM_STATUS_UNSUCCESSFUL; 00144 } 00145 00146 return MM_STATUS_SUCCESS; 00147 } 00148 00149 MIXER_STATUS 00150 Control( 00151 IN HANDLE hMixer, 00152 IN ULONG dwIoControlCode, 00153 IN PVOID lpInBuffer, 00154 IN ULONG nInBufferSize, 00155 OUT PVOID lpOutBuffer, 00156 ULONG nOutBufferSize, 00157 PULONG lpBytesReturned) 00158 { 00159 OVERLAPPED Overlapped; 00160 BOOLEAN IoResult; 00161 DWORD Transferred = 0; 00162 00163 /* Overlapped I/O is done here - this is used for waiting for completion */ 00164 ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); 00165 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 00166 00167 if ( ! Overlapped.hEvent ) 00168 return MM_STATUS_NO_MEMORY; 00169 00170 /* Talk to the device */ 00171 IoResult = DeviceIoControl(hMixer, 00172 dwIoControlCode, 00173 lpInBuffer, 00174 nInBufferSize, 00175 lpOutBuffer, 00176 nOutBufferSize, 00177 &Transferred, 00178 &Overlapped); 00179 00180 /* If failure occurs, make sure it's not just due to the overlapped I/O */ 00181 if ( ! IoResult ) 00182 { 00183 if ( GetLastError() != ERROR_IO_PENDING ) 00184 { 00185 CloseHandle(Overlapped.hEvent); 00186 00187 if (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER) 00188 { 00189 if ( lpBytesReturned ) 00190 *lpBytesReturned = Transferred; 00191 return MM_STATUS_MORE_ENTRIES; 00192 } 00193 00194 return MM_STATUS_UNSUCCESSFUL; 00195 } 00196 } 00197 00198 /* Wait for the I/O to complete */ 00199 IoResult = GetOverlappedResult(hMixer, 00200 &Overlapped, 00201 &Transferred, 00202 TRUE); 00203 00204 /* Don't need this any more */ 00205 CloseHandle(Overlapped.hEvent); 00206 00207 if ( ! IoResult ) 00208 return MM_STATUS_UNSUCCESSFUL; 00209 00210 if ( lpBytesReturned ) 00211 *lpBytesReturned = Transferred; 00212 00213 return MM_STATUS_SUCCESS; 00214 } 00215 00216 MIXER_STATUS 00217 Enum( 00218 IN PVOID EnumContext, 00219 IN ULONG DeviceIndex, 00220 OUT LPWSTR * DeviceName, 00221 OUT PHANDLE OutHandle, 00222 OUT PHANDLE OutKey) 00223 { 00224 SP_DEVICE_INTERFACE_DATA InterfaceData; 00225 SP_DEVINFO_DATA DeviceData; 00226 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData; 00227 BOOL Result; 00228 DWORD Length; 00229 MIXER_STATUS Status; 00230 00231 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle); 00232 00233 InterfaceData.cbSize = sizeof(InterfaceData); 00234 InterfaceData.Reserved = 0; 00235 00236 Result = SetupDiEnumDeviceInterfaces(EnumContext, 00237 NULL, 00238 &CategoryGuid, 00239 DeviceIndex, 00240 &InterfaceData); 00241 00242 if (!Result) 00243 { 00244 if (GetLastError() == ERROR_NO_MORE_ITEMS) 00245 { 00246 return MM_STATUS_NO_MORE_DEVICES; 00247 } 00248 return MM_STATUS_UNSUCCESSFUL; 00249 } 00250 00251 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR); 00252 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 00253 0, 00254 Length); 00255 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); 00256 DeviceData.cbSize = sizeof(DeviceData); 00257 DeviceData.Reserved = 0; 00258 00259 Result = SetupDiGetDeviceInterfaceDetailW(EnumContext, 00260 &InterfaceData, 00261 DetailData, 00262 Length, 00263 NULL, 00264 &DeviceData); 00265 00266 if (!Result) 00267 { 00268 DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError()); 00269 return MM_STATUS_UNSUCCESSFUL; 00270 } 00271 00272 00273 *OutKey = SetupDiOpenDeviceInterfaceRegKey(EnumContext, &InterfaceData, 0, KEY_READ); 00274 if ((HKEY)*OutKey == INVALID_HANDLE_VALUE) 00275 { 00276 HeapFree(GetProcessHeap(), 0, DetailData); 00277 return MM_STATUS_UNSUCCESSFUL; 00278 } 00279 00280 Status = Open(DetailData->DevicePath, OutHandle); 00281 00282 if (Status != MM_STATUS_SUCCESS) 00283 { 00284 RegCloseKey((HKEY)*OutKey); 00285 HeapFree(GetProcessHeap(), 0, DetailData); 00286 return Status; 00287 } 00288 00289 *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR)); 00290 if (*DeviceName == NULL) 00291 { 00292 CloseHandle(*OutHandle); 00293 RegCloseKey((HKEY)*OutKey); 00294 HeapFree(GetProcessHeap(), 0, DetailData); 00295 return MM_STATUS_NO_MEMORY; 00296 } 00297 wcscpy(*DeviceName, DetailData->DevicePath); 00298 HeapFree(GetProcessHeap(), 0, DetailData); 00299 00300 return Status; 00301 } 00302 00303 PVOID 00304 AllocEventData( 00305 IN ULONG ExtraSize) 00306 { 00307 PKSEVENTDATA Data = (PKSEVENTDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSEVENTDATA) + ExtraSize); 00308 if (!Data) 00309 return NULL; 00310 00311 Data->EventHandle.Event = CreateEventW(NULL, FALSE, FALSE, NULL); 00312 if (!Data->EventHandle.Event) 00313 { 00314 HeapFree(GetProcessHeap(), 0, Data); 00315 return NULL; 00316 } 00317 00318 Data->NotificationType = KSEVENTF_EVENT_HANDLE; 00319 return Data; 00320 } 00321 00322 VOID 00323 FreeEventData(IN PVOID EventData) 00324 { 00325 PKSEVENTDATA Data = (PKSEVENTDATA)EventData; 00326 00327 CloseHandle(Data->EventHandle.Event); 00328 HeapFree(GetProcessHeap(), 0, Data); 00329 } 00330 00331 00332 BOOL 00333 WdmAudInitUserModeMixer() 00334 { 00335 HDEVINFO DeviceHandle; 00336 MIXER_STATUS Status; 00337 00338 if (MMixerLibraryInitialized) 00339 { 00340 /* library is already initialized */ 00341 return TRUE; 00342 } 00343 00344 00345 /* create a device list */ 00346 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, 00347 NULL, 00348 NULL, 00349 DIGCF_DEVICEINTERFACE/* FIXME |DIGCF_PRESENT*/); 00350 00351 if (DeviceHandle == INVALID_HANDLE_VALUE) 00352 { 00353 /* failed to create a device list */ 00354 return FALSE; 00355 } 00356 00357 00358 /* initialize the mixer library */ 00359 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle); 00360 00361 /* free device list */ 00362 SetupDiDestroyDeviceInfoList(DeviceHandle); 00363 00364 if (Status != MM_STATUS_SUCCESS) 00365 { 00366 /* failed to initialize mixer library */ 00367 DPRINT1("Failed to initialize mixer library with %x\n", Status); 00368 return FALSE; 00369 } 00370 00371 /* library is now initialized */ 00372 MMixerLibraryInitialized = TRUE; 00373 00374 /* completed successfully */ 00375 return TRUE; 00376 } 00377 00378 MMRESULT 00379 WdmAudCleanupByMMixer() 00380 { 00381 /* TODO */ 00382 return MMSYSERR_NOERROR; 00383 } 00384 00385 MMRESULT 00386 WdmAudGetMixerCapabilties( 00387 IN ULONG DeviceId, 00388 LPMIXERCAPSW Capabilities) 00389 { 00390 if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) 00391 return MMSYSERR_NOERROR; 00392 00393 return MMSYSERR_BADDEVICEID; 00394 } 00395 00396 MMRESULT 00397 WdmAudGetLineInfo( 00398 IN HANDLE hMixer, 00399 IN DWORD MixerId, 00400 IN LPMIXERLINEW MixLine, 00401 IN ULONG Flags) 00402 { 00403 if (MMixerGetLineInfo(&MixerContext, hMixer, MixerId, Flags, MixLine) == MM_STATUS_SUCCESS) 00404 return MMSYSERR_NOERROR; 00405 00406 return MMSYSERR_ERROR; 00407 } 00408 00409 MMRESULT 00410 WdmAudGetLineControls( 00411 IN HANDLE hMixer, 00412 IN DWORD MixerId, 00413 IN LPMIXERLINECONTROLSW MixControls, 00414 IN ULONG Flags) 00415 { 00416 if (MMixerGetLineControls(&MixerContext, hMixer, MixerId, Flags, MixControls) == MM_STATUS_SUCCESS) 00417 return MMSYSERR_NOERROR; 00418 00419 return MMSYSERR_ERROR; 00420 } 00421 00422 MMRESULT 00423 WdmAudSetControlDetails( 00424 IN HANDLE hMixer, 00425 IN DWORD MixerId, 00426 IN LPMIXERCONTROLDETAILS MixDetails, 00427 IN ULONG Flags) 00428 { 00429 if (MMixerSetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) 00430 return MMSYSERR_NOERROR; 00431 00432 return MMSYSERR_ERROR; 00433 00434 } 00435 00436 MMRESULT 00437 WdmAudGetControlDetails( 00438 IN HANDLE hMixer, 00439 IN DWORD MixerId, 00440 IN LPMIXERCONTROLDETAILS MixDetails, 00441 IN ULONG Flags) 00442 { 00443 if (MMixerGetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) 00444 return MMSYSERR_NOERROR; 00445 00446 return MMSYSERR_ERROR; 00447 } 00448 00449 MMRESULT 00450 WdmAudGetWaveOutCapabilities( 00451 IN ULONG DeviceId, 00452 LPWAVEOUTCAPSW Capabilities) 00453 { 00454 if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) 00455 return MMSYSERR_NOERROR; 00456 00457 return MMSYSERR_ERROR; 00458 00459 } 00460 00461 MMRESULT 00462 WdmAudGetWaveInCapabilities( 00463 IN ULONG DeviceId, 00464 LPWAVEINCAPSW Capabilities) 00465 { 00466 if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) 00467 return MMSYSERR_NOERROR; 00468 00469 return MMSYSERR_ERROR; 00470 } 00471 00472 MMRESULT 00473 WdmAudSetWaveDeviceFormatByMMixer( 00474 IN PSOUND_DEVICE_INSTANCE Instance, 00475 IN DWORD DeviceId, 00476 IN PWAVEFORMATEX WaveFormat, 00477 IN DWORD WaveFormatSize) 00478 { 00479 MMDEVICE_TYPE DeviceType; 00480 PSOUND_DEVICE SoundDevice; 00481 MMRESULT Result; 00482 BOOL bWaveIn; 00483 00484 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); 00485 00486 if ( ! MMSUCCESS(Result) ) 00487 { 00488 return TranslateInternalMmResult(Result); 00489 } 00490 00491 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00492 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00493 00494 bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE); 00495 00496 if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS) 00497 { 00498 if (DeviceType == WAVE_OUT_DEVICE_TYPE) 00499 { 00500 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE); 00501 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE); 00502 MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN); 00503 } 00504 return MMSYSERR_NOERROR; 00505 } 00506 return MMSYSERR_ERROR; 00507 } 00508 00509 00510 MMRESULT 00511 WdmAudGetCapabilitiesByMMixer( 00512 IN PSOUND_DEVICE SoundDevice, 00513 IN DWORD DeviceId, 00514 OUT PVOID Capabilities, 00515 IN DWORD CapabilitiesSize) 00516 { 00517 MMDEVICE_TYPE DeviceType; 00518 MMRESULT Result; 00519 00520 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00521 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00522 00523 if (DeviceType == MIXER_DEVICE_TYPE) 00524 { 00525 return WdmAudGetMixerCapabilties(DeviceId, (LPMIXERCAPSW)Capabilities); 00526 } 00527 else if (DeviceType == WAVE_OUT_DEVICE_TYPE) 00528 { 00529 return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities); 00530 } 00531 else if (DeviceType == WAVE_IN_DEVICE_TYPE) 00532 { 00533 return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities); 00534 } 00535 else 00536 { 00537 // not supported 00538 return MMSYSERR_ERROR; 00539 } 00540 } 00541 00542 MMRESULT 00543 WdmAudOpenSoundDeviceByMMixer( 00544 IN struct _SOUND_DEVICE* SoundDevice, 00545 OUT PVOID* Handle) 00546 { 00547 if (WdmAudInitUserModeMixer()) 00548 return MMSYSERR_NOERROR; 00549 else 00550 return MMSYSERR_ERROR; 00551 } 00552 00553 MMRESULT 00554 WdmAudCloseSoundDeviceByMMixer( 00555 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 00556 IN PVOID Handle) 00557 { 00558 MMDEVICE_TYPE DeviceType; 00559 PSOUND_DEVICE SoundDevice; 00560 MMRESULT Result; 00561 00562 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00563 00564 if ( ! MMSUCCESS(Result) ) 00565 { 00566 return TranslateInternalMmResult(Result); 00567 } 00568 00569 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00570 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00571 00572 if (DeviceType == MIXER_DEVICE_TYPE) 00573 { 00574 /* no op */ 00575 return MMSYSERR_NOERROR; 00576 } 00577 else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) 00578 { 00579 /* make sure the pin is stopped */ 00580 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); 00581 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); 00582 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); 00583 00584 CloseHandle(Handle); 00585 return MMSYSERR_NOERROR; 00586 } 00587 00588 /* midi is not supported */ 00589 return MMSYSERR_ERROR; 00590 } 00591 00592 MMRESULT 00593 WdmAudGetNumWdmDevsByMMixer( 00594 IN MMDEVICE_TYPE DeviceType, 00595 OUT DWORD* DeviceCount) 00596 { 00597 switch(DeviceType) 00598 { 00599 case MIXER_DEVICE_TYPE: 00600 *DeviceCount = MMixerGetCount(&MixerContext); 00601 break; 00602 case WAVE_OUT_DEVICE_TYPE: 00603 *DeviceCount = MMixerGetWaveOutCount(&MixerContext); 00604 break; 00605 case WAVE_IN_DEVICE_TYPE: 00606 *DeviceCount = MMixerGetWaveInCount(&MixerContext); 00607 break; 00608 default: 00609 *DeviceCount = 0; 00610 } 00611 return MMSYSERR_NOERROR; 00612 } 00613 00614 MMRESULT 00615 WdmAudQueryMixerInfoByMMixer( 00616 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 00617 IN DWORD MixerId, 00618 IN UINT uMsg, 00619 IN LPVOID Parameter, 00620 IN DWORD Flags) 00621 { 00622 LPMIXERLINEW MixLine; 00623 LPMIXERLINECONTROLSW MixControls; 00624 LPMIXERCONTROLDETAILS MixDetails; 00625 HANDLE hMixer = NULL; 00626 00627 MixLine = (LPMIXERLINEW)Parameter; 00628 MixControls = (LPMIXERLINECONTROLSW)Parameter; 00629 MixDetails = (LPMIXERCONTROLDETAILS)Parameter; 00630 00631 /* FIXME param checks */ 00632 00633 if (SoundDeviceInstance) 00634 { 00635 hMixer = SoundDeviceInstance->Handle; 00636 } 00637 00638 switch(uMsg) 00639 { 00640 case MXDM_GETLINEINFO: 00641 return WdmAudGetLineInfo(hMixer, MixerId, MixLine, Flags); 00642 case MXDM_GETLINECONTROLS: 00643 return WdmAudGetLineControls(hMixer, MixerId, MixControls, Flags); 00644 case MXDM_SETCONTROLDETAILS: 00645 return WdmAudSetControlDetails(hMixer, MixerId, MixDetails, Flags); 00646 case MXDM_GETCONTROLDETAILS: 00647 return WdmAudGetControlDetails(hMixer, MixerId, MixDetails, Flags); 00648 default: 00649 DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags); 00650 SND_ASSERT(0); 00651 return MMSYSERR_NOTSUPPORTED; 00652 } 00653 } 00654 00655 MMRESULT 00656 WdmAudGetDeviceInterfaceStringByMMixer( 00657 IN MMDEVICE_TYPE DeviceType, 00658 IN DWORD DeviceId, 00659 IN LPWSTR Interface, 00660 IN DWORD InterfaceLength, 00661 OUT DWORD * InterfaceSize) 00662 { 00663 /* FIXME */ 00664 return MMSYSERR_NOTSUPPORTED; 00665 } 00666 00667 VOID 00668 CALLBACK 00669 MixerEventCallback( 00670 IN PVOID MixerEventContext, 00671 IN HANDLE hMixer, 00672 IN ULONG NotificationType, 00673 IN ULONG Value) 00674 { 00675 PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)MixerEventContext; 00676 00677 DriverCallback(Instance->WinMM.ClientCallback, 00678 HIWORD(Instance->WinMM.Flags), 00679 Instance->WinMM.Handle, 00680 NotificationType, 00681 Instance->WinMM.ClientCallbackInstanceData, 00682 (DWORD_PTR)Value, 00683 0); 00684 } 00685 00686 MMRESULT 00687 WdmAudSetMixerDeviceFormatByMMixer( 00688 IN PSOUND_DEVICE_INSTANCE Instance, 00689 IN DWORD DeviceId, 00690 IN PWAVEFORMATEX WaveFormat, 00691 IN DWORD WaveFormatSize) 00692 { 00693 if (MMixerOpen(&MixerContext, DeviceId, (PVOID)Instance, MixerEventCallback, &Instance->Handle) == MM_STATUS_SUCCESS) 00694 return MMSYSERR_NOERROR; 00695 00696 return MMSYSERR_BADDEVICEID; 00697 } 00698 00699 MMRESULT 00700 WdmAudSetWaveStateByMMixer( 00701 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 00702 IN BOOL bStart) 00703 { 00704 MMDEVICE_TYPE DeviceType; 00705 PSOUND_DEVICE SoundDevice; 00706 MMRESULT Result; 00707 00708 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00709 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00710 00711 00712 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00713 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00714 00715 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) 00716 { 00717 if (bStart) 00718 { 00719 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); 00720 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); 00721 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); 00722 } 00723 else 00724 { 00725 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); 00726 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); 00727 MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); 00728 } 00729 } 00730 else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) 00731 { 00732 if (bStart) 00733 { 00734 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); 00735 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); 00736 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); 00737 } 00738 else 00739 { 00740 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); 00741 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); 00742 MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); 00743 } 00744 } 00745 00746 return MMSYSERR_NOERROR; 00747 } 00748 00749 MMRESULT 00750 WdmAudResetStreamByMMixer( 00751 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 00752 IN MMDEVICE_TYPE DeviceType, 00753 IN BOOLEAN bStartReset) 00754 { 00755 MIXER_STATUS Status; 00756 00757 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) 00758 { 00759 Status = MMixerSetWaveResetState(&MixerContext, SoundDeviceInstance->Handle, bStartReset); 00760 if (Status == MM_STATUS_SUCCESS) 00761 { 00762 /* completed successfully */ 00763 return MMSYSERR_NOERROR; 00764 } 00765 } 00766 00767 00768 return MMSYSERR_NOTSUPPORTED; 00769 } 00770 00771 MMRESULT 00772 WdmAudGetWavePositionByMMixer( 00773 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 00774 IN MMTIME* Time) 00775 { 00776 /* FIXME */ 00777 return MMSYSERR_NOTSUPPORTED; 00778 } 00779 00780 DWORD 00781 WINAPI 00782 IoStreamingThread( 00783 LPVOID lpParameter) 00784 { 00785 DWORD Length; 00786 //MMRESULT Result; 00787 LPIO_PACKET Packet = (LPIO_PACKET)lpParameter; 00788 00789 /*Result = */ SyncOverlappedDeviceIoControl(Packet->hDevice, 00790 Packet->IoCtl, 00791 NULL, 00792 0, 00793 &Packet->Header, 00794 sizeof(KSSTREAM_HEADER), 00795 &Length); 00796 00797 Packet->CompletionRoutine(ERROR_SUCCESS, Packet->Header.DataUsed, (LPOVERLAPPED)Packet->Overlap); 00798 00799 HeapFree(GetProcessHeap(), 0, Packet); 00800 return 0; 00801 } 00802 00803 MMRESULT 00804 WdmAudCommitWaveBufferByMMixer( 00805 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 00806 IN PVOID OffsetPtr, 00807 IN DWORD Length, 00808 IN PSOUND_OVERLAPPED Overlap, 00809 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) 00810 { 00811 PSOUND_DEVICE SoundDevice; 00812 MMDEVICE_TYPE DeviceType; 00813 MMRESULT Result; 00814 LPIO_PACKET Packet; 00815 HANDLE hThread; 00816 00817 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); 00818 00819 if ( ! MMSUCCESS(Result) ) 00820 { 00821 return TranslateInternalMmResult(Result); 00822 } 00823 00824 Result = GetSoundDeviceType(SoundDevice, &DeviceType); 00825 SND_ASSERT( Result == MMSYSERR_NOERROR ); 00826 00827 Packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IO_PACKET)); 00828 if ( ! Packet ) 00829 { 00830 /* no memory */ 00831 return MMSYSERR_NOMEM; 00832 } 00833 00834 /* setup stream packet */ 00835 Packet->Header.Size = sizeof(KSSTREAM_HEADER); 00836 Packet->Header.PresentationTime.Numerator = 1; 00837 Packet->Header.PresentationTime.Denominator = 1; 00838 Packet->Header.Data = OffsetPtr; 00839 Packet->Header.FrameExtent = Length; 00840 Packet->hDevice = SoundDeviceInstance->Handle; 00841 Packet->Overlap = Overlap; 00842 Packet->CompletionRoutine = CompletionRoutine; 00843 Packet->IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); 00844 00845 if (DeviceType == WAVE_OUT_DEVICE_TYPE) 00846 { 00847 Packet->Header.DataUsed = Length; 00848 } 00849 00850 hThread = CreateThread(NULL, 0, IoStreamingThread, (LPVOID)Packet, 0, NULL); 00851 if (hThread == NULL) 00852 { 00853 /* error */ 00854 return MMSYSERR_ERROR; 00855 } 00856 00857 CloseHandle(hThread); 00858 00859 return MMSYSERR_NOERROR; 00860 } Generated on Sun May 27 2012 04:26:52 for ReactOS by
1.7.6.1
|