[MMIXER]
[reactos.git] / reactos / lib / drivers / sound / mmixer / mixer.c
index 279d119..94c3a2a 100644 (file)
 
 #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;
+    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
+
+    // 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);
+        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 LPMIXERLINECONTROLS 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,
@@ -17,9 +409,12 @@ MMixerInitialize(
     IN PVOID EnumContext)
 {
     MIXER_STATUS Status;
-    HANDLE hMixer;
+    HANDLE hMixer, hKey;
     ULONG DeviceIndex, Count;
     LPWSTR DeviceName;
+    LPMIXER_DATA MixerData;
+    PMIXER_LIST MixerList;
+    PLIST_ENTRY Entry;
 
     if (!MixerContext || !EnumFunction || !EnumContext)
     {
@@ -27,12 +422,29 @@ MMixerInitialize(
         return MM_STATUS_INVALID_PARAMETER;
     }
 
-    if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free)
+    if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open || 
+        !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;
+     InitializeListHead(&MixerList->MixerList);
+     InitializeListHead(&MixerList->MixerData);
+
+     // store mixer list
+     MixerContext->MixerContext = (PVOID)MixerList;
 
     // start enumerating all available devices
     Count = 0;
@@ -41,33 +453,39 @@ MMixerInitialize(
     do
     {
         // enumerate a device
-        Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer);
+        Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
 
         if (Status != MM_STATUS_SUCCESS)
         {
             //check error code
-            if (Status != MM_STATUS_NO_MORE_DEVICES)
+            if (Status == MM_STATUS_NO_MORE_DEVICES)
             {
-                // enumeration has failed
-                return Status;
+                // enumeration has finished
+                break;
             }
-            // last device
-            break;
         }
-
+        else
+        {
+            // create a mixer data entry
+            Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
+            if (Status != MM_STATUS_SUCCESS)
+                break;
+        }
 
         // increment device index
         DeviceIndex++;
-
-        Status = MMixerSetupFilter(MixerContext, hMixer, &Count, DeviceName);
-
-        if (Status != MM_STATUS_SUCCESS)
-            break;
-
     }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 Status;
+    return MM_STATUS_SUCCESS;
 }
-
-