ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mmixer.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.