mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
2d0dd58947
svn path=/branches/reactos-yarotows/; revision=47795
509 lines
14 KiB
C
509 lines
14 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel Streaming
|
|
* FILE: lib/drivers/sound/mmixer/mmixer.c
|
|
* PURPOSE: Mixer Handling Functions
|
|
* PROGRAMMER: Johannes Anderwald
|
|
*/
|
|
|
|
|
|
|
|
#include "priv.h"
|
|
|
|
ULONG
|
|
MMixerGetCount(
|
|
IN PMIXER_CONTEXT MixerContext)
|
|
{
|
|
PMIXER_LIST MixerList;
|
|
MIXER_STATUS Status;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
// grab mixer list
|
|
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
|
|
|
|
// return number of mixers
|
|
return MixerList->MixerListCount;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerGetCapabilities(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN ULONG MixerIndex,
|
|
OUT LPMIXERCAPSW MixerCaps)
|
|
{
|
|
MIXER_STATUS Status;
|
|
LPMIXER_INFO MixerInfo;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
// get mixer info
|
|
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex);
|
|
|
|
if (!MixerInfo)
|
|
{
|
|
// invalid device index
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
MixerCaps->wMid = MixerInfo->MixCaps.wMid;
|
|
MixerCaps->wPid = MixerInfo->MixCaps.wPid;
|
|
MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
|
|
MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport;
|
|
MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations;
|
|
|
|
ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
|
|
wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname);
|
|
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerOpen(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN ULONG MixerId,
|
|
IN PVOID MixerEvent,
|
|
IN PMIXER_EVENT MixerEventRoutine,
|
|
OUT PHANDLE MixerHandle)
|
|
{
|
|
MIXER_STATUS Status;
|
|
LPMIXER_INFO MixerInfo;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
|
|
if (!MixerInfo)
|
|
{
|
|
// invalid mixer id
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// FIXME
|
|
// handle event notification
|
|
|
|
Status = MMixerAddEvents(MixerContext, MixerInfo);
|
|
|
|
|
|
// store result
|
|
*MixerHandle = (HANDLE)MixerInfo;
|
|
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerGetLineInfo(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN HANDLE MixerHandle,
|
|
IN ULONG Flags,
|
|
OUT LPMIXERLINEW MixerLine)
|
|
{
|
|
MIXER_STATUS Status;
|
|
LPMIXER_INFO MixerInfo;
|
|
LPMIXERLINE_EXT MixerLineSrc;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
// clear hmixer from flags
|
|
Flags &=~MIXER_OBJECTF_HMIXER;
|
|
|
|
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
if (MixerLine->dwDestination != 0)
|
|
{
|
|
// destination line member must be zero
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
|
ASSERT(MixerLineSrc);
|
|
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
|
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
|
ASSERT(MixerLineSrc);
|
|
|
|
if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
|
|
{
|
|
DPRINT1("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections);
|
|
|
|
// invalid parameter
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwSource * 0x10000);
|
|
if (MixerLineSrc)
|
|
{
|
|
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
|
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
return MM_STATUS_UNSUCCESSFUL;
|
|
}
|
|
else if (Flags == MIXER_GETLINEINFOF_LINEID)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
|
|
if (!MixerLineSrc)
|
|
{
|
|
// invalid parameter
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* copy cached data */
|
|
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
|
|
if (!MixerLineSrc)
|
|
{
|
|
DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType);
|
|
return MM_STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
ASSERT(MixerLineSrc);
|
|
|
|
/* copy cached data */
|
|
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
|
|
return MM_STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerGetLineControls(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN HANDLE MixerHandle,
|
|
IN ULONG Flags,
|
|
OUT LPMIXERLINECONTROLSW MixerLineControls)
|
|
{
|
|
LPMIXER_INFO MixerInfo;
|
|
LPMIXERLINE_EXT MixerLineSrc;
|
|
LPMIXERCONTROLW MixerControl;
|
|
MIXER_STATUS Status;
|
|
ULONG Index;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
Flags &= ~MIXER_OBJECTF_HMIXER;
|
|
|
|
if (Flags == MIXER_GETLINECONTROLSF_ALL)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
|
|
|
if (!MixerLineSrc)
|
|
{
|
|
// invalid line id
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
// copy line control(s)
|
|
MixerContext->Copy(MixerLineControls->pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, MixerLineControls->cControls) * sizeof(MIXERCONTROLW));
|
|
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
|
|
|
if (!MixerLineSrc)
|
|
{
|
|
// invalid line id
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
ASSERT(MixerLineSrc);
|
|
|
|
Index = 0;
|
|
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
|
{
|
|
DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType);
|
|
if (MixerLineControls->dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
|
|
{
|
|
// found a control with that type
|
|
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
|
|
return MM_STATUS_UNSUCCESSFUL;
|
|
}
|
|
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
|
|
{
|
|
// cast to mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid parameter
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// copy the controls
|
|
MixerContext->Copy(MixerLineControls->pamxctrl, MixerControl, sizeof(MIXERCONTROLW));
|
|
return MM_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
return MM_STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerSetControlDetails(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN HANDLE MixerHandle,
|
|
IN ULONG Flags,
|
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
|
{
|
|
MIXER_STATUS Status;
|
|
ULONG NodeId;
|
|
LPMIXER_INFO MixerInfo;
|
|
LPMIXERLINE_EXT MixerLine;
|
|
LPMIXERCONTROLW MixerControl;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
// get mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
// get mixer control
|
|
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
|
|
|
|
// check for success
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// failed to find control id
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch(MixerControl->dwControlType)
|
|
{
|
|
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
|
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
|
|
break;
|
|
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
|
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
|
|
break;
|
|
default:
|
|
Status = MM_STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerGetControlDetails(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN HANDLE MixerHandle,
|
|
IN ULONG Flags,
|
|
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
|
{
|
|
MIXER_STATUS Status;
|
|
ULONG NodeId;
|
|
LPMIXER_INFO MixerInfo;
|
|
LPMIXERLINE_EXT MixerLine;
|
|
LPMIXERCONTROLW MixerControl;
|
|
|
|
// verify mixer context
|
|
Status = MMixerVerifyContext(MixerContext);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// invalid context passed
|
|
return Status;
|
|
}
|
|
|
|
// get mixer info
|
|
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
|
|
|
// get mixer control
|
|
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
|
|
|
|
// check for success
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
// failed to find control id
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch(MixerControl->dwControlType)
|
|
{
|
|
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
|
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
|
|
break;
|
|
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
|
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
|
|
break;
|
|
default:
|
|
Status = MM_STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
MIXER_STATUS
|
|
MMixerInitialize(
|
|
IN PMIXER_CONTEXT MixerContext,
|
|
IN PMIXER_ENUM EnumFunction,
|
|
IN PVOID EnumContext)
|
|
{
|
|
MIXER_STATUS Status;
|
|
HANDLE hMixer, hKey;
|
|
ULONG DeviceIndex, Count;
|
|
LPWSTR DeviceName;
|
|
LPMIXER_DATA MixerData;
|
|
PMIXER_LIST MixerList;
|
|
PLIST_ENTRY Entry;
|
|
|
|
if (!MixerContext || !EnumFunction || !EnumContext)
|
|
{
|
|
// invalid parameter
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open ||
|
|
!MixerContext->AllocEventData || !MixerContext->FreeEventData ||
|
|
!MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
|
|
{
|
|
// invalid parameter
|
|
return MM_STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// allocate a mixer list
|
|
MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
|
|
if (!MixerList)
|
|
{
|
|
// no memory
|
|
return MM_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
//initialize mixer list
|
|
MixerList->MixerListCount = 0;
|
|
MixerList->MixerDataCount = 0;
|
|
MixerList->WaveInListCount = 0;
|
|
MixerList->WaveOutListCount = 0;
|
|
InitializeListHead(&MixerList->MixerList);
|
|
InitializeListHead(&MixerList->MixerData);
|
|
InitializeListHead(&MixerList->WaveInList);
|
|
InitializeListHead(&MixerList->WaveOutList);
|
|
|
|
|
|
// store mixer list
|
|
MixerContext->MixerContext = (PVOID)MixerList;
|
|
|
|
// start enumerating all available devices
|
|
Count = 0;
|
|
DeviceIndex = 0;
|
|
|
|
do
|
|
{
|
|
// enumerate a device
|
|
Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
|
|
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
{
|
|
//check error code
|
|
if (Status == MM_STATUS_NO_MORE_DEVICES)
|
|
{
|
|
// enumeration has finished
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
|
|
|
|
// TODO cleanup
|
|
return Status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// create a mixer data entry
|
|
Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
|
|
if (Status != MM_STATUS_SUCCESS)
|
|
break;
|
|
}
|
|
|
|
// increment device index
|
|
DeviceIndex++;
|
|
}while(TRUE);
|
|
|
|
//now all filters have been pre-opened
|
|
// lets enumerate the filters
|
|
Entry = MixerList->MixerData.Flink;
|
|
while(Entry != &MixerList->MixerData)
|
|
{
|
|
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
|
|
MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count);
|
|
Entry = Entry->Flink;
|
|
}
|
|
|
|
// done
|
|
return MM_STATUS_SUCCESS;
|
|
}
|