⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mixer.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * ReactOS Sound Volume Control
 * Copyright (C) 2004-2005 Thomas Weidenmueller
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/* $Id: mixer.c 25206 2006-12-22 21:49:18Z cwittich $
 *
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS Sound Volume Control
 * FILE:        subsys/system/sndvol32/mixer.c
 * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
 */
#include <sndvol32.h>

#define NO_MIXER_SELECTED ((UINT)(~0))

static VOID
ClearMixerCache(PSND_MIXER Mixer)
{
    PSND_MIXER_DESTINATION Line, NextLine;
    PSND_MIXER_CONNECTION Con, NextCon;

    for (Line = Mixer->Lines; Line != NULL; Line = NextLine)
    {
        if (Line->Controls != NULL)
        {
            HeapFree(GetProcessHeap(),
                     0,
                     Line->Controls);
        }

        for (Con = Line->Connections; Con != NULL; Con = NextCon)
        {
            if (Con->Controls != NULL)
            {
                HeapFree(GetProcessHeap(),
                         0,
                         Con->Controls);
            }

            NextCon = Con->Next;
            HeapFree(GetProcessHeap(),
                     0,
                     Con);
        }

        NextLine = Line->Next;
        HeapFree(GetProcessHeap(),
                 0,
                 Line);
    }
    Mixer->Lines = NULL;
}

PSND_MIXER
SndMixerCreate(HWND hWndNotification)
{
    PSND_MIXER Mixer = (PSND_MIXER) HeapAlloc(GetProcessHeap(),
                                 HEAP_ZERO_MEMORY,
                                 sizeof(SND_MIXER));
    if (Mixer != NULL)
    {
        Mixer->hWndNotification = hWndNotification;
        Mixer->MixersCount = mixerGetNumDevs();
        Mixer->MixerId = NO_MIXER_SELECTED;

        if (Mixer->MixersCount > 0)
        {
            /* select the first mixer by default */
            SndMixerSelect(Mixer, 0);
        }
    }

    return Mixer;
}

VOID
SndMixerDestroy(PSND_MIXER Mixer)
{
    SndMixerClose(Mixer);
    HeapFree(GetProcessHeap(),
             0,
             Mixer);
}

VOID
SndMixerClose(PSND_MIXER Mixer)
{
    if (Mixer->hmx != NULL)
    {
      mixerClose(Mixer->hmx);
      Mixer->hmx = NULL;
      Mixer->MixerId = NO_MIXER_SELECTED;
    }
}

static BOOL
SndMixerQueryControls(PSND_MIXER Mixer,
                      PUINT DisplayControls,
                      LPMIXERLINE LineInfo,
                      LPMIXERCONTROL *Controls)
{
    if (LineInfo->cControls > 0)
    {
        *Controls = (MIXERCONTROL*) HeapAlloc(GetProcessHeap(),
                              0,
                              LineInfo->cControls * sizeof(MIXERCONTROL));
        if (*Controls != NULL)
        {
            MIXERLINECONTROLS LineControls;
            MMRESULT Result;
            UINT j;

            LineControls.cbStruct = sizeof(LineControls);
            LineControls.dwLineID = LineInfo->dwLineID;
            LineControls.cControls = LineInfo->cControls;
            LineControls.cbmxctrl = sizeof(MIXERCONTROL);
            LineControls.pamxctrl = (MIXERCONTROL*)(*Controls);

            Result = mixerGetLineControls((HMIXEROBJ)Mixer->hmx,
                                          &LineControls,
                                          MIXER_GETLINECONTROLSF_ALL);
            if (Result == MMSYSERR_NOERROR)
            {
                for (j = 0; j < LineControls.cControls; j++)
                {
                    if (SndMixerIsDisplayControl(Mixer,
                                                 &(*Controls)[j]))
                    {
                        (*DisplayControls)++;
                    }

                    DPRINT("Line control: %ws (0x%x, 0x%x)\n", (*Controls)[j].szName, (*Controls)[j].fdwControl, (*Controls)[j].dwControlType);
                }

                return TRUE;
            }
            else
            {
                HeapFree(GetProcessHeap(),
                         0,
                         *Controls);
                *Controls = NULL;
                DPRINT("Failed to get line (ID: 0x%x) controls: %d\n", LineInfo->dwLineID, Result);
            }
        }
        else
        {
            DPRINT("Failed to allocate memory for %d line (ID: 0x%x) controls!\n", LineInfo->dwLineID, LineInfo->cControls);
        }

        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

static BOOL
SndMixerQueryConnections(PSND_MIXER Mixer,
                         PSND_MIXER_DESTINATION Line)
{
    UINT i, DispControls;
    MIXERLINE LineInfo;
    MMRESULT Result;
    BOOL Ret = TRUE;

    LineInfo.cbStruct = sizeof(LineInfo);
    for (i = Line->Info.cConnections; i > 0; i--)
    {
        LineInfo.dwDestination = Line->Info.dwDestination;
        LineInfo.dwSource = i - 1;
        Result = mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
                                  &LineInfo,
                                  MIXER_GETLINEINFOF_SOURCE);
        if (Result == MMSYSERR_NOERROR)
        {
            LPMIXERCONTROL Controls;
            PSND_MIXER_CONNECTION Con;

            DPRINT("++ Source: %ws\n", LineInfo.szName);

            DispControls = 0;

            if (!SndMixerQueryControls(Mixer,
                                       &DispControls,
                                       &LineInfo,
                                       &Controls))
            {
                DPRINT("Failed to query connection controls\n");
                Ret = FALSE;
                break;
            }

            Con = (SND_MIXER_CONNECTION*) HeapAlloc(GetProcessHeap(),
                            0,
                            sizeof(SND_MIXER_CONNECTION));
            if (Con != NULL)
            {
                Con->Info = LineInfo;
                Con->Controls = Controls;
                Con->DisplayControls = DispControls;
                Con->Next = Line->Connections;
                Line->Connections = Con;
            }
            else
            {
                HeapFree(GetProcessHeap(),
                         0,
                         Controls);
            }
        }
        else
        {
            DPRINT("Failed to get connection information: %d\n", Result);
            Ret = FALSE;
            break;
        }
    }

    return Ret;
}

static BOOL
SndMixerQueryDestinations(PSND_MIXER Mixer)
{
    UINT i;
    BOOL Ret = TRUE;

    for (i = Mixer->Caps.cDestinations; i > 0; i--)
    {
        PSND_MIXER_DESTINATION Line;

        Line = (SND_MIXER_DESTINATION*) HeapAlloc(GetProcessHeap(),
                         HEAP_ZERO_MEMORY,
                         sizeof(SND_MIXER_DESTINATION));
        if (Line != NULL)
        {
            Line->Info.cbStruct = sizeof(Line->Info);
            Line->Info.dwDestination = i - 1;
            if (mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
                                 &Line->Info,
                                 MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR)
            {
                DPRINT("+ Destination: %ws (0x%x, %d)\n", Line->Info.szName, Line->Info.dwLineID, Line->Info.dwComponentType);

                if (!SndMixerQueryControls(Mixer,
                                           &Line->DisplayControls,
                                           &Line->Info,
                                           &Line->Controls))
                {
                    DPRINT("Failed to query mixer controls!\n");
                    Ret = FALSE;
                    break;
                }

                if (!SndMixerQueryConnections(Mixer, Line))
                {
                    DPRINT("Failed to query mixer connections!\n");
                    Ret = FALSE;
                    break;
                }

                Line->Next = Mixer->Lines;
                Mixer->Lines = Line;
            }
            else
            {
                DPRINT("Failed to get line information for id %d!\n", i);
                HeapFree(GetProcessHeap(),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -