- 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
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)
}
}
- 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");
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));
}
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;
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;
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;
}
+
MMixerOpen(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
- IN PVOID MixerEvent,
+ IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine,
OUT PHANDLE MixerHandle)
{
return Status;
}
+ /* get mixer info */
MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerInfo)
{
return MM_STATUS_INVALID_PARAMETER;
}
- /* FIXME
- * handle event notification
- */
-
- Status = MMixerAddEvents(MixerContext, MixerInfo);
+ /* add the event */
+ Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
/* store result */
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;
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,
MMixerOpen(
IN PMIXER_CONTEXT MixerContext,
IN ULONG MixerId,
- IN PVOID MixerEvent,
+ IN PVOID MixerEventContext,
IN PMIXER_EVENT MixerEventRoutine,
OUT PHANDLE MixerHandle);
}TOPOLOGY, *PTOPOLOGY;
-
-typedef struct
-{
- KSEVENTDATA EventData;
- LIST_ENTRY Entry;
-}EVENT_ITEM, *LPEVENT_ITEM;
-
typedef struct
{
LIST_ENTRY Entry;
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
MIXER_STATUS
MMixerSetGetMuteControlDetails(
IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
+ IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG dwLineID,
IN LPMIXERCONTROLDETAILS MixerControlDetails,
MIXER_STATUS
MMixerSetGetVolumeControlDetails(
IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
+ IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG bSet,
LPMIXERCONTROLW MixerControl,
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 */
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,
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;
}
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;
MIXER_STATUS
MMixerSetGetVolumeControlDetails(
IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
+ IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
IN ULONG bSet,
LPMIXERCONTROLW MixerControl,
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)
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;
}
MixerData->hDeviceInterfaceKey = hKey;
MixerData->Topology = NULL;
-
-
InsertTailList(&MixerList->MixerData, &MixerData->Entry);
MixerList->MixerDataCount++;
return MM_STATUS_SUCCESS;