[WDMAUD_KERNEL]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 15 Oct 2010 02:24:35 +0000 (02:24 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 15 Oct 2010 02:24:35 +0000 (02:24 +0000)
- 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

reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c
reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
reactos/lib/drivers/sound/mmixer/controls.c
reactos/lib/drivers/sound/mmixer/mixer.c
reactos/lib/drivers/sound/mmixer/mmixer.h
reactos/lib/drivers/sound/mmixer/priv.h
reactos/lib/drivers/sound/mmixer/sup.c

index 397bf99..72e7776 100644 (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));
 }
 
index 0258c8e..dff0d8f 100644 (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;
index 543fb1e..8870669 100644 (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;
 }
+
index 9b317ce..cd6b0a0 100644 (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;
index 0cfc4ac..c7abbb6 100644 (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);
 
index 489bd98..1cf3391 100644 (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 */
 
index 90aee6e..a557cf9 100644 (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;