[WDMAUD_KERNEL]

- Implement registering event routine which gets called when a topology node (volume / mute node) changes
- Implement fetching event changes
[MMIXER]
- Implement support routines which get called when a topology node changes its state
- Volume changes / mute on/off changes should now be broadcasted again to all listening applications

svn path=/trunk/; revision=49151
This commit is contained in:
Johannes Anderwald 2010-10-15 02:24:35 +00:00
parent 8a0913d231
commit 8158082c80
7 changed files with 165 additions and 75 deletions

View file

@ -318,6 +318,53 @@ FreeEventData(IN PVOID EventData)
FreeItem(Data);
}
VOID
EventCallback(
IN PVOID MixerEventContext,
IN HANDLE hMixer,
IN ULONG NotificationType,
IN ULONG Value)
{
PWDMAUD_CLIENT ClientInfo;
PEVENT_ENTRY Entry;
ULONG Index;
/* get client context */
ClientInfo = (PWDMAUD_CLIENT)MixerEventContext;
/* now search for the mixer which originated the request */
for(Index = 0; Index < ClientInfo->NumPins; Index++)
{
if (ClientInfo->hPins[Index].Handle == hMixer && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
{
if (ClientInfo->hPins[Index].NotifyEvent)
{
/* allocate event entry */
Entry = AllocateItem(NonPagedPool, sizeof(EVENT_ENTRY));
if (!Entry)
{
/* no memory */
break;
}
/* setup event entry */
Entry->NotificationType = NotificationType;
Entry->Value = Value;
Entry->hMixer = hMixer;
/* insert entry */
InsertTailList(&ClientInfo->MixerEventList, &Entry->Entry);
/* now notify the client */
KeSetEvent(ClientInfo->hPins[Index].NotifyEvent, 0, FALSE);
}
/* done */
break;
}
}
}
NTSTATUS
WdmAudMixerInitialize(
IN PDEVICE_OBJECT DeviceObject)
@ -378,7 +425,7 @@ WdmAudControlOpenMixer(
}
}
if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS)
if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS)
{
ObDereferenceObject(EventObject);
DPRINT1("Failed to open mixer\n");
@ -511,7 +558,39 @@ WdmAudGetMixerEvent(
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
UNIMPLEMENTED
PLIST_ENTRY Entry;
PEVENT_ENTRY EventEntry;
/* enumerate event list and check if there is a new event */
Entry = ClientInfo->MixerEventList.Flink;
while(Entry != &ClientInfo->MixerEventList)
{
/* grab event entry */
EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry);
if (EventEntry->hMixer == DeviceInfo->hDevice)
{
/* found an entry */
DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer;
DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType;
DeviceInfo->u.MixerEvent.Value = EventEntry->Value;
/* remove entry from list */
RemoveEntryList(&EventEntry->Entry);
/* free event entry */
FreeItem(EventEntry);
/* done */
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
/* move to next */
Entry = Entry->Flink;
}
/* no event entry available */
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}

View file

@ -35,6 +35,14 @@ typedef struct
LIST_ENTRY MixerEventList;
}WDMAUD_CLIENT, *PWDMAUD_CLIENT;
typedef struct
{
LIST_ENTRY Entry;
ULONG NotificationType;
ULONG Value;
HANDLE hMixer;
}EVENT_ENTRY, *PEVENT_ENTRY;
typedef struct
{
LIST_ENTRY Entry;

View file

@ -1086,20 +1086,22 @@ MIXER_STATUS
MMixerAddEvent(
IN PMIXER_CONTEXT MixerContext,
IN OUT LPMIXER_INFO MixerInfo,
IN ULONG NodeId)
IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine)
{
KSE_NODE Property;
LPEVENT_ITEM EventData;
ULONG BytesReturned;
MIXER_STATUS Status;
//KSE_NODE Property;
PEVENT_NOTIFICATION_ENTRY EventData;
//ULONG BytesReturned;
//MIXER_STATUS Status;
EventData = (LPEVENT_ITEM)MixerContext->AllocEventData(sizeof(LIST_ENTRY));
EventData = (PEVENT_NOTIFICATION_ENTRY)MixerContext->AllocEventData(sizeof(EVENT_NOTIFICATION_ENTRY));
if (!EventData)
{
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
#if 0
/* setup request */
Property.Event.Set = KSEVENTSETID_AudioControlChange;
Property.Event.Flags = KSEVENT_TYPE_TOPOLOGY|KSEVENT_TYPE_ENABLE;
@ -1115,45 +1117,14 @@ MMixerAddEvent(
MixerContext->FreeEventData(EventData);
return Status;
}
#endif
/* initialize notification entry */
EventData->MixerEventContext = MixerEventContext;
EventData->MixerEventRoutine;
/* store event */
InsertTailList(&MixerInfo->EventList, &EventData->Entry);
return Status;
}
MIXER_STATUS
MMixerAddEvents(
IN PMIXER_CONTEXT MixerContext,
IN OUT LPMIXER_INFO MixerInfo)
{
PKSMULTIPLE_ITEM NodeTypes;
ULONG Index;
MIXER_STATUS Status;
LPGUID Guid;
/* get filter node types */
Status = MMixerGetFilterTopologyProperty(MixerContext, MixerInfo->hMixer, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
if (Status != MM_STATUS_SUCCESS)
{
/* failed */
return Status;
}
for(Index = 0; Index < NodeTypes->Count; Index++)
{
Guid = MMixerGetNodeType(NodeTypes, Index);
if (IsEqualGUID(&KSNODETYPE_VOLUME, Guid) || IsEqualGUID(&KSNODETYPE_MUTE, Guid))
{
/* add an event for volume / mute controls
* TODO: support extra control types
*/
MMixerAddEvent(MixerContext, MixerInfo, Index);
}
}
/* free node types */
MixerContext->Free(NodeTypes);
return MM_STATUS_SUCCESS;
}

View file

@ -76,7 +76,7 @@ MIXER_STATUS
MMixerOpen(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
IN PVOID MixerEvent,
IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine,
OUT PHANDLE MixerHandle)
{
@ -92,6 +92,7 @@ MMixerOpen(
return Status;
}
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerInfo)
{
@ -99,11 +100,8 @@ MMixerOpen(
return MM_STATUS_INVALID_PARAMETER;
}
/* FIXME
* handle event notification
*/
Status = MMixerAddEvents(MixerContext, MixerInfo);
/* add the event */
Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
/* store result */
@ -396,10 +394,10 @@ MMixerGetControlDetails(
switch(MixerControl->dwControlType)
{
case MIXERCONTROL_CONTROLTYPE_MUTE:
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
break;
case MIXERCONTROL_CONTROLTYPE_VOLUME:
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
break;
default:
Status = MM_STATUS_NOT_IMPLEMENTED;

View file

@ -48,7 +48,10 @@ typedef MIXER_STATUS(*PMIXER_CLOSEKEY)(
IN HANDLE hKey);
typedef VOID (*PMIXER_EVENT)(
IN PVOID MixerEvent);
IN PVOID MixerEventContext,
IN HANDLE hMixer,
IN ULONG NotificationType,
IN ULONG Value);
typedef VOID (*PMIXER_COPY)(
IN PVOID Dst,
@ -130,7 +133,7 @@ MIXER_STATUS
MMixerOpen(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
IN PVOID MixerEvent,
IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine,
OUT PHANDLE MixerHandle);

View file

@ -62,13 +62,6 @@ typedef struct
}TOPOLOGY, *PTOPOLOGY;
typedef struct
{
KSEVENTDATA EventData;
LIST_ENTRY Entry;
}EVENT_ITEM, *LPEVENT_ITEM;
typedef struct
{
LIST_ENTRY Entry;
@ -141,6 +134,14 @@ typedef struct
LIST_ENTRY WaveOutList;
}MIXER_LIST, *PMIXER_LIST;
typedef struct
{
LIST_ENTRY Entry;
PVOID MixerEventContext;
PMIXER_EVENT MixerEventRoutine;
}EVENT_NOTIFICATION_ENTRY, *PEVENT_NOTIFICATION_ENTRY;
#define DESTINATION_LINE 0xFFFF0000
ULONG
@ -262,7 +263,7 @@ MMixerGetMixerControlById(
MIXER_STATUS
MMixerSetGetMuteControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG dwLineID,
IN LPMIXERCONTROLDETAILS MixerControlDetails,
@ -271,7 +272,7 @@ MMixerSetGetMuteControlDetails(
MIXER_STATUS
MMixerSetGetVolumeControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG bSet,
LPMIXERCONTROLW MixerControl,
@ -324,9 +325,11 @@ MMixerInitializeWaveInfo(
IN PULONG Pins);
MIXER_STATUS
MMixerAddEvents(
MMixerAddEvent(
IN PMIXER_CONTEXT MixerContext,
IN OUT LPMIXER_INFO MixerInfo);
IN OUT LPMIXER_INFO MixerInfo,
IN PVOID MixerEvent,
IN PMIXER_EVENT MixerEventRoutine);
/* topology.c */

View file

@ -233,10 +233,38 @@ MMixerGetVolumeControlIndex(
return VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1);
}
VOID
MMixerNotifyControlChange(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo,
IN ULONG NotificationType,
IN ULONG Value)
{
PLIST_ENTRY Entry;
PEVENT_NOTIFICATION_ENTRY NotificationEntry;
/* enumerate list and add a notification entry */
Entry = MixerInfo->LineList.Flink;
while(Entry != &MixerInfo->EventList)
{
/* get notification entry offset */
NotificationEntry = (PEVENT_NOTIFICATION_ENTRY)CONTAINING_RECORD(Entry, EVENT_NOTIFICATION_ENTRY, Entry);
if (NotificationEntry->MixerEventRoutine)
{
/* now perform the callback */
NotificationEntry->MixerEventRoutine(NotificationEntry->MixerEventContext, (HANDLE)MixerInfo, NotificationType, Value);
}
/* move to next notification entry */
Entry = Entry->Flink;
}
}
MIXER_STATUS
MMixerSetGetMuteControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG dwLineID,
IN LPMIXERCONTROLDETAILS MixerControlDetails,
@ -257,7 +285,7 @@ MMixerSetGetMuteControlDetails(
Value = Input->fValue;
/* set control details */
Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
if (Status != MM_STATUS_SUCCESS)
return Status;
@ -270,7 +298,8 @@ MMixerSetGetMuteControlDetails(
}
else
{
/* FIXME notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID */
/* notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID */
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_LINE_CHANGE, dwLineID);
}
return Status;
@ -279,7 +308,7 @@ MMixerSetGetMuteControlDetails(
MIXER_STATUS
MMixerSetGetVolumeControlDetails(
IN PMIXER_CONTEXT MixerContext,
IN HANDLE hMixer,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG bSet,
LPMIXERCONTROLW MixerControl,
@ -322,12 +351,12 @@ MMixerSetGetVolumeControlDetails(
if (bSet)
{
/* TODO */
Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
}
else
{
Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
}
if (!bSet)
@ -339,6 +368,7 @@ MMixerSetGetVolumeControlDetails(
else
{
/* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->dwControlID);
}
return Status;
}
@ -407,8 +437,6 @@ MMixerCreateMixerData(
MixerData->hDeviceInterfaceKey = hKey;
MixerData->Topology = NULL;
InsertTailList(&MixerList->MixerData, &MixerData->Entry);
MixerList->MixerDataCount++;
return MM_STATUS_SUCCESS;