📄 mixer.c
字号:
/*
* 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 + -