add sndvol32 to the build system and reformat the code

svn path=/trunk/; revision=18102
This commit is contained in:
Thomas Bluemel 2005-09-26 19:15:27 +00:00
parent 469b041e51
commit d286c03c70
7 changed files with 816 additions and 528 deletions

View file

@ -55,6 +55,9 @@
<directory name="sm"> <directory name="sm">
<xi:include href="sm/sm.xml" /> <xi:include href="sm/sm.xml" />
</directory> </directory>
<directory name="sndvol32">
<xi:include href="sndvol32/sndvol32.xml" />
</directory>
<directory name="taskmgr"> <directory name="taskmgr">
<xi:include href="taskmgr/taskmgr.xml" /> <xi:include href="taskmgr/taskmgr.xml" />
</directory> </directory>

View file

@ -13,7 +13,7 @@ BEGIN
BEGIN BEGIN
MENUITEM "&Help Topics", IDC_HELP_TOPICS MENUITEM "&Help Topics", IDC_HELP_TOPICS
MENUITEM SEPARATOR MENUITEM SEPARATOR
MENUITEM "&About ...", IDC_ABOUT MENUITEM "&About Volume Control", IDC_ABOUT
END END
END END

View file

@ -0,0 +1,129 @@
/*
* 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
*
* VMware is a registered trademark of VMware, Inc.
*/
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Sound Volume Control
* FILE: subsys/system/sndvol32/misc.c
* PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
*/
#include <sndvol32.h>
static INT
LengthOfStrResource(IN HINSTANCE hInst,
IN UINT uID)
{
HRSRC hrSrc;
HGLOBAL hRes;
LPWSTR lpName, lpStr;
if (hInst == NULL)
{
return -1;
}
/* There are always blocks of 16 strings */
lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
/* Find the string table block */
if ((hrSrc = FindResourceW(hInst,
lpName,
(LPWSTR)RT_STRING)) &&
(hRes = LoadResource(hInst,
hrSrc)) &&
(lpStr = LockResource(hRes)))
{
UINT x;
/* Find the string we're looking for */
uID &= 0xF; /* position in the block, same as % 16 */
for (x = 0; x < uID; x++)
{
lpStr += (*lpStr) + 1;
}
/* Found the string */
return (int)(*lpStr);
}
return -1;
}
INT
AllocAndLoadString(OUT LPWSTR *lpTarget,
IN HINSTANCE hInst,
IN UINT uID)
{
INT ln;
ln = LengthOfStrResource(hInst,
uID);
if (ln++ > 0)
{
(*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED,
ln * sizeof(WCHAR));
if ((*lpTarget) != NULL)
{
INT Ret;
if (!(Ret = LoadStringW(hInst,
uID,
*lpTarget,
ln)))
{
LocalFree((HLOCAL)(*lpTarget));
}
return Ret;
}
}
return 0;
}
DWORD
LoadAndFormatString(IN HINSTANCE hInstance,
IN UINT uID,
OUT LPWSTR *lpTarget,
...)
{
DWORD Ret = 0;
LPWSTR lpFormat;
va_list lArgs;
if (AllocAndLoadString(&lpFormat,
hInstance,
uID) > 0)
{
va_start(lArgs, lpTarget);
/* let's use FormatMessage to format it because it has the ability to
allocate memory automatically */
Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
lpFormat,
0,
0,
(LPWSTR)lpTarget,
0,
&lArgs);
va_end(lArgs);
LocalFree((HLOCAL)lpFormat);
}
return Ret;
}

View file

@ -1,6 +1,6 @@
/* /*
* ReactOS Sound Volume Control * ReactOS Sound Volume Control
* Copyright (C) 2004 Thomas Weidenmueller * Copyright (C) 2004-2005 Thomas Weidenmueller
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -25,354 +25,423 @@
* FILE: subsys/system/sndvol32/mixer.c * FILE: subsys/system/sndvol32/mixer.c
* PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com> * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
*/ */
#include "sndvol32.h" #include <sndvol32.h>
#define NO_MIXER_SELECTED (~0) #define NO_MIXER_SELECTED (~0)
static VOID static VOID
ClearMixerCache(PSND_MIXER Mixer) ClearMixerCache(PSND_MIXER Mixer)
{ {
PSND_MIXER_DESTINATION Line, NextLine; PSND_MIXER_DESTINATION Line, NextLine;
PSND_MIXER_CONNECTION Con, NextCon; PSND_MIXER_CONNECTION Con, NextCon;
for(Line = Mixer->Lines; Line != NULL; Line = NextLine) for (Line = Mixer->Lines; Line != NULL; Line = NextLine)
{
if(Line->Controls != NULL)
{ {
HeapFree(GetProcessHeap(), 0, Line->Controls); 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;
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 PSND_MIXER
SndMixerCreate(HWND hWndNotification) SndMixerCreate(HWND hWndNotification)
{ {
PSND_MIXER Mixer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SND_MIXER)); PSND_MIXER Mixer = HeapAlloc(GetProcessHeap(),
if(Mixer != NULL) HEAP_ZERO_MEMORY,
{ sizeof(SND_MIXER));
Mixer->hWndNotification = hWndNotification; if (Mixer != NULL)
Mixer->MixersCount = mixerGetNumDevs();
Mixer->MixerId = NO_MIXER_SELECTED;
if(Mixer->MixersCount > 0)
{ {
/* select the first mixer by default */ Mixer->hWndNotification = hWndNotification;
SndMixerSelect(Mixer, 0); Mixer->MixersCount = mixerGetNumDevs();
} Mixer->MixerId = NO_MIXER_SELECTED;
}
return Mixer; if (Mixer->MixersCount > 0)
{
/* select the first mixer by default */
SndMixerSelect(Mixer, 0);
}
}
return Mixer;
} }
VOID VOID
SndMixerDestroy(PSND_MIXER Mixer) SndMixerDestroy(PSND_MIXER Mixer)
{ {
SndMixerClose(Mixer); SndMixerClose(Mixer);
HeapFree(GetProcessHeap(), 0, Mixer); HeapFree(GetProcessHeap(),
0,
Mixer);
} }
VOID VOID
SndMixerClose(PSND_MIXER Mixer) SndMixerClose(PSND_MIXER Mixer)
{ {
if(Mixer->hmx != NULL) if (Mixer->hmx != NULL)
{ {
mixerClose(Mixer->hmx); mixerClose(Mixer->hmx);
Mixer->hmx = NULL; Mixer->hmx = NULL;
Mixer->MixerId = NO_MIXER_SELECTED; Mixer->MixerId = NO_MIXER_SELECTED;
} }
} }
static BOOL static BOOL
SndMixerQueryControls(PSND_MIXER Mixer, LPMIXERLINE LineInfo, LPMIXERCONTROL *Controls) SndMixerQueryControls(PSND_MIXER Mixer,
LPMIXERLINE LineInfo,
LPMIXERCONTROL *Controls)
{ {
if(LineInfo->cControls > 0) if (LineInfo->cControls > 0)
{
*Controls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, LineInfo->cControls * sizeof(MIXERCONTROL));
if(*Controls != NULL)
{ {
MIXERLINECONTROLS LineControls; *Controls = HeapAlloc(GetProcessHeap(),
UINT j; HEAP_ZERO_MEMORY,
LineInfo->cControls * sizeof(MIXERCONTROL));
LineControls.cbStruct = sizeof(LineControls); if (*Controls != NULL)
LineControls.dwLineID = LineInfo->dwLineID;
LineControls.cControls = LineInfo->cControls;
LineControls.cbmxctrl = sizeof(MIXERCONTROL);
LineControls.pamxctrl = (PVOID)(*Controls);
for(j = 0; j < LineInfo->cControls; j++)
{
(*Controls)[j].cbStruct = sizeof(MIXERCONTROL);
}
if(mixerGetLineControls((HMIXEROBJ)Mixer->hmx, &LineControls, MIXER_GETLINECONTROLSF_ALL) == MMSYSERR_NOERROR)
{
for(j = 0; j < LineInfo->cControls; j++)
{ {
DBG("Line control: %ws", (*Controls)[j].szName); MIXERLINECONTROLS LineControls;
UINT j;
LineControls.cbStruct = sizeof(LineControls);
LineControls.dwLineID = LineInfo->dwLineID;
LineControls.cControls = LineInfo->cControls;
LineControls.cbmxctrl = sizeof(MIXERCONTROL);
LineControls.pamxctrl = (PVOID)(*Controls);
for (j = 0; j < LineInfo->cControls; j++)
{
(*Controls)[j].cbStruct = sizeof(MIXERCONTROL);
}
if (mixerGetLineControls((HMIXEROBJ)Mixer->hmx,
&LineControls,
MIXER_GETLINECONTROLSF_ALL) == MMSYSERR_NOERROR)
{
for (j = 0; j < LineInfo->cControls; j++)
{
DPRINT("Line control: %ws", (*Controls)[j].szName);
}
return TRUE;
}
else
{
HeapFree(GetProcessHeap(),
0,
*Controls);
*Controls = NULL;
DPRINT("Failed to get line controls!\n");
}
}
else
{
DPRINT("Failed to allocate memory for %d line controls!\n", LineInfo->cControls);
} }
return TRUE; return FALSE;
}
else
{
HeapFree(GetProcessHeap(), 0, *Controls);
*Controls = NULL;
DBG("Failed to get line controls!\n");
}
} }
else else
{ {
DBG("Failed to allocate memory for %d line controls!\n", LineInfo->cControls); return TRUE;
} }
return FALSE;
}
else
{
return TRUE;
}
} }
static BOOL static BOOL
SndMixerQueryConnections(PSND_MIXER Mixer, PSND_MIXER_DESTINATION Line) SndMixerQueryConnections(PSND_MIXER Mixer,
PSND_MIXER_DESTINATION Line)
{ {
UINT i; UINT i;
MIXERLINE LineInfo; MIXERLINE LineInfo;
BOOL Ret = TRUE; BOOL Ret = TRUE;
LineInfo.cbStruct = sizeof(LineInfo); LineInfo.cbStruct = sizeof(LineInfo);
LineInfo.dwDestination = Line->Info.dwDestination; LineInfo.dwDestination = Line->Info.dwDestination;
for(i = Line->Info.cConnections; i > 0; i--) for (i = Line->Info.cConnections; i > 0; i--)
{
LineInfo.dwSource = i - 1;
if(mixerGetLineInfo((HMIXEROBJ)Mixer->hmx, &LineInfo, MIXER_GETLINEINFOF_SOURCE) == MMSYSERR_NOERROR)
{ {
LPMIXERCONTROL Controls; LineInfo.dwSource = i - 1;
PSND_MIXER_CONNECTION Con; if (mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
&LineInfo,
MIXER_GETLINEINFOF_SOURCE) == MMSYSERR_NOERROR)
{
LPMIXERCONTROL Controls;
PSND_MIXER_CONNECTION Con;
if(!SndMixerQueryControls(Mixer, &LineInfo, &Controls)) if (!SndMixerQueryControls(Mixer,
{ &LineInfo,
DBG("Failed to query connection controls\n"); &Controls))
Ret = FALSE; {
break; DPRINT("Failed to query connection controls\n");
} Ret = FALSE;
break;
}
Con = HeapAlloc(GetProcessHeap(), 0, sizeof(SND_MIXER_CONNECTION)); Con = HeapAlloc(GetProcessHeap(),
if(Con != NULL) 0,
{ sizeof(SND_MIXER_CONNECTION));
Con->Info = LineInfo; if (Con != NULL)
Con->Controls = Controls; {
Con->Next = Line->Connections; Con->Info = LineInfo;
Line->Connections = Con; Con->Controls = Controls;
} Con->Next = Line->Connections;
else Line->Connections = Con;
{ }
HeapFree(GetProcessHeap(), 0, Controls); else
} {
HeapFree(GetProcessHeap(),
0,
Controls);
}
}
else
{
DPRINT("Failed to get connection information!\n");
Ret = FALSE;
break;
}
} }
else
{
DBG("Failed to get connection information!\n");
Ret = FALSE;
break;
}
}
return Ret; return Ret;
} }
static BOOL static BOOL
SndMixerQueryDestinations(PSND_MIXER Mixer) SndMixerQueryDestinations(PSND_MIXER Mixer)
{ {
UINT i; UINT i;
BOOL Ret = TRUE; BOOL Ret = TRUE;
for(i = Mixer->Caps.cDestinations; i > 0; i--) for (i = Mixer->Caps.cDestinations; i > 0; i--)
{
PSND_MIXER_DESTINATION Line;
Line = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SND_MIXER_DESTINATION));
if(Line != NULL)
{ {
Line->Info.cbStruct = sizeof(Line->Info); PSND_MIXER_DESTINATION Line;
Line->Info.dwDestination = i - 1;
if(mixerGetLineInfo((HMIXEROBJ)Mixer->hmx, &Line->Info, MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR)
{
if(!SndMixerQueryConnections(Mixer, Line))
{
DBG("Failed to query mixer connections!\n");
Ret = FALSE;
break;
}
if(!SndMixerQueryControls(Mixer, &Line->Info, &Line->Controls))
{
DBG("Failed to query mixer controls!\n");
Ret = FALSE;
break;
}
Line->Next = Mixer->Lines; Line = HeapAlloc(GetProcessHeap(),
Mixer->Lines = Line; HEAP_ZERO_MEMORY,
} sizeof(SND_MIXER_DESTINATION));
else if (Line != NULL)
{ {
DBG("Failed to get line information for id %d!\n", i); Line->Info.cbStruct = sizeof(Line->Info);
HeapFree(GetProcessHeap(), 0, Line); Line->Info.dwDestination = i - 1;
Ret = FALSE; if (mixerGetLineInfo((HMIXEROBJ)Mixer->hmx,
break; &Line->Info,
} MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR)
} {
else if (!SndMixerQueryConnections(Mixer, Line))
{ {
DBG("Allocation of SND_MIXER_DEST structure for id %d failed!\n", i); DPRINT("Failed to query mixer connections!\n");
Ret = FALSE; Ret = FALSE;
break; break;
} }
} if (!SndMixerQueryControls(Mixer,
&Line->Info,
&Line->Controls))
{
DPRINT("Failed to query mixer controls!\n");
Ret = FALSE;
break;
}
return Ret; Line->Next = Mixer->Lines;
Mixer->Lines = Line;
}
else
{
DPRINT("Failed to get line information for id %d!\n", i);
HeapFree(GetProcessHeap(),
0,
Line);
Ret = FALSE;
break;
}
}
else
{
DPRINT("Allocation of SND_MIXER_DEST structure for id %d failed!\n", i);
Ret = FALSE;
break;
}
}
return Ret;
} }
BOOL BOOL
SndMixerSelect(PSND_MIXER Mixer, UINT MixerId) SndMixerSelect(PSND_MIXER Mixer,
UINT MixerId)
{ {
if(MixerId >= Mixer->MixersCount) if (MixerId >= Mixer->MixersCount)
{ {
return FALSE;
}
SndMixerClose(Mixer);
if (mixerOpen(&Mixer->hmx,
MixerId,
(DWORD_PTR)Mixer->hWndNotification,
0,
CALLBACK_WINDOW | MIXER_OBJECTF_MIXER) == MMSYSERR_NOERROR ||
mixerOpen(&Mixer->hmx,
MixerId,
(DWORD_PTR)Mixer->hWndNotification,
0,
CALLBACK_WINDOW) == MMSYSERR_NOERROR ||
mixerOpen(&Mixer->hmx,
MixerId,
0,
0,
0) == MMSYSERR_NOERROR)
{
if (mixerGetDevCaps(MixerId,
&Mixer->Caps,
sizeof(Mixer->Caps)) == MMSYSERR_NOERROR)
{
BOOL Ret = FALSE;
Mixer->MixerId = MixerId;
ClearMixerCache(Mixer);
Ret = SndMixerQueryDestinations(Mixer);
if (!Ret)
{
ClearMixerCache(Mixer);
}
return Ret;
}
else
{
mixerClose(Mixer->hmx);
}
}
Mixer->hmx = NULL;
Mixer->MixerId = NO_MIXER_SELECTED;
return FALSE; return FALSE;
}
SndMixerClose(Mixer);
if(mixerOpen(&Mixer->hmx, MixerId, (DWORD_PTR)Mixer->hWndNotification, 0, CALLBACK_WINDOW | MIXER_OBJECTF_MIXER) == MMSYSERR_NOERROR ||
mixerOpen(&Mixer->hmx, MixerId, (DWORD_PTR)Mixer->hWndNotification, 0, CALLBACK_WINDOW) == MMSYSERR_NOERROR ||
mixerOpen(&Mixer->hmx, MixerId, 0, 0, 0) == MMSYSERR_NOERROR)
{
if(mixerGetDevCaps(MixerId, &Mixer->Caps, sizeof(Mixer->Caps)) == MMSYSERR_NOERROR)
{
BOOL Ret = FALSE;
Mixer->MixerId = MixerId;
ClearMixerCache(Mixer);
Ret = SndMixerQueryDestinations(Mixer);
if(!Ret)
{
ClearMixerCache(Mixer);
}
return Ret;
}
else
{
mixerClose(Mixer->hmx);
}
}
Mixer->hmx = NULL;
Mixer->MixerId = NO_MIXER_SELECTED;
return FALSE;
} }
UINT UINT
SndMixerGetSelection(PSND_MIXER Mixer) SndMixerGetSelection(PSND_MIXER Mixer)
{ {
return Mixer->MixerId; return Mixer->MixerId;
} }
INT INT
SndMixerGetProductName(PSND_MIXER Mixer, LPTSTR lpBuffer, UINT uSize) SndMixerGetProductName(PSND_MIXER Mixer,
LPTSTR lpBuffer,
UINT uSize)
{ {
if(Mixer->hmx) if (Mixer->hmx)
{
int lnsz = lstrlen(Mixer->Caps.szPname);
if(lnsz + 1 > uSize)
{ {
return lnsz + 1; int lnsz = lstrlen(Mixer->Caps.szPname);
if(lnsz + 1 > uSize)
{
return lnsz + 1;
}
else
{
memcpy(lpBuffer, Mixer->Caps.szPname, lnsz * sizeof(TCHAR));
lpBuffer[lnsz] = _T('\0');
return lnsz;
}
} }
else
{
memcpy(lpBuffer, Mixer->Caps.szPname, lnsz * sizeof(TCHAR));
lpBuffer[lnsz] = _T('\0');
return lnsz;
}
}
return -1; return -1;
} }
BOOL BOOL
SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOID Context) SndMixerEnumProducts(PSND_MIXER Mixer,
PFNSNDMIXENUMPRODUCTS EnumProc,
PVOID Context)
{ {
MIXERCAPS Caps; MIXERCAPS Caps;
HMIXER hMixer; HMIXER hMixer;
UINT i; UINT i;
BOOL Ret = TRUE; BOOL Ret = TRUE;
for(i = 0; i < Mixer->MixersCount; i++) for (i = 0; i < Mixer->MixersCount; i++)
{
if(mixerOpen(&hMixer, i, 0, 0, 0) == MMSYSERR_NOERROR)
{ {
if(mixerGetDevCaps(i, &Caps, sizeof(Caps)) == MMSYSERR_NOERROR) if (mixerOpen(&hMixer,
{ i,
if(!EnumProc(Mixer, i, Caps.szPname, Context)) 0,
0,
0) == MMSYSERR_NOERROR)
{ {
mixerClose(hMixer); if (mixerGetDevCaps(i,
Ret = FALSE; &Caps,
break; sizeof(Caps)) == MMSYSERR_NOERROR)
{
if (!EnumProc(Mixer,
i,
Caps.szPname,
Context))
{
mixerClose(hMixer);
Ret = FALSE;
break;
}
}
else
{
DPRINT("Failed to get device capabilities for mixer id %d!\n", i);
}
mixerClose(hMixer);
} }
}
else
{
DBG("Failed to get device capabilities for mixer id %d!\n", i);
}
mixerClose(hMixer);
} }
}
return Ret; return Ret;
} }
INT INT
SndMixerGetDestinationCount(PSND_MIXER Mixer) SndMixerGetDestinationCount(PSND_MIXER Mixer)
{ {
return (Mixer->hmx ? Mixer->Caps.cDestinations : -1); return (Mixer->hmx ? Mixer->Caps.cDestinations : -1);
} }
BOOL BOOL
SndMixerEnumLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context) SndMixerEnumLines(PSND_MIXER Mixer,
PFNSNDMIXENUMLINES EnumProc,
PVOID Context)
{ {
if(Mixer->hmx) if (Mixer->hmx)
{
PSND_MIXER_DESTINATION Line;
for(Line = Mixer->Lines; Line != NULL; Line = Line->Next)
{ {
if(!EnumProc(Mixer, &Line->Info, Context)) PSND_MIXER_DESTINATION Line;
{
return FALSE; for (Line = Mixer->Lines; Line != NULL; Line = Line->Next)
} {
if (!EnumProc(Mixer,
&Line->Info,
Context))
{
return FALSE;
}
}
return TRUE;
} }
return TRUE; return FALSE;
}
return FALSE;
} }

View file

@ -1,6 +1,6 @@
/* /*
* ReactOS Sound Volume Control * ReactOS Sound Volume Control
* Copyright (C) 2004 Thomas Weidenmueller * Copyright (C) 2004-2005 Thomas Weidenmueller
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -25,7 +25,7 @@
* FILE: subsys/system/sndvol32/sndvol32.c * FILE: subsys/system/sndvol32/sndvol32.c
* PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com> * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
*/ */
#include "sndvol32.h" #include <sndvol32.h>
HINSTANCE hAppInstance; HINSTANCE hAppInstance;
ATOM MainWindowClass; ATOM MainWindowClass;
@ -33,116 +33,137 @@ HWND hMainWnd;
HANDLE hAppHeap; HANDLE hAppHeap;
#define GetDialogData(hwndDlg, type) \ #define GetDialogData(hwndDlg, type) \
( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER) ( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER)
#define GetWindowData(hwnd, type) \ #define GetWindowData(hwnd, type) \
( P##type )GetWindowLongPtr((hwnd), GWL_USERDATA) ( P##type )GetWindowLongPtr((hwnd), GWL_USERDATA)
/******************************************************************************/ /******************************************************************************/
typedef struct _PREFERENCES_CONTEXT typedef struct _PREFERENCES_CONTEXT
{ {
PMIXER_WINDOW MixerWindow; PMIXER_WINDOW MixerWindow;
PSND_MIXER Mixer; PSND_MIXER Mixer;
HWND hwndDlg; HWND hwndDlg;
} PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT; } PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT;
typedef struct _PREFERENCES_FILL_DEVICES typedef struct _PREFERENCES_FILL_DEVICES
{ {
PPREFERENCES_CONTEXT PrefContext; PPREFERENCES_CONTEXT PrefContext;
HWND hComboBox; HWND hComboBox;
UINT Selected; UINT Selected;
} PREFERENCES_FILL_DEVICES, *PPREFERENCES_FILL_DEVICES; } PREFERENCES_FILL_DEVICES, *PPREFERENCES_FILL_DEVICES;
static BOOL CALLBACK static BOOL CALLBACK
FillDeviceComboBox(PSND_MIXER Mixer, UINT Id, LPCTSTR ProductName, PVOID Context) FillDeviceComboBox(PSND_MIXER Mixer,
UINT Id,
LPCTSTR ProductName,
PVOID Context)
{ {
LRESULT lres; LRESULT lres;
PPREFERENCES_FILL_DEVICES FillContext = (PPREFERENCES_FILL_DEVICES)Context; PPREFERENCES_FILL_DEVICES FillContext = (PPREFERENCES_FILL_DEVICES)Context;
lres = SendMessage(FillContext->hComboBox, CB_ADDSTRING, 0, (LPARAM)ProductName); lres = SendMessage(FillContext->hComboBox,
if(lres != CB_ERR) CB_ADDSTRING,
{ 0,
/* save the index so we don't screw stuff when the combobox is sorted... */ (LPARAM)ProductName);
SendMessage(FillContext->hComboBox, CB_SETITEMDATA, (WPARAM)lres, Id); if (lres != CB_ERR)
if(Id == FillContext->Selected)
{ {
SendMessage(FillContext->hComboBox, CB_SETCURSEL, (WPARAM)lres, 0); /* save the index so we don't screw stuff when the combobox is sorted... */
} SendMessage(FillContext->hComboBox,
} CB_SETITEMDATA,
(WPARAM)lres,
Id);
return TRUE; if (Id == FillContext->Selected)
{
SendMessage(FillContext->hComboBox,
CB_SETCURSEL,
(WPARAM)lres,
0);
}
}
return TRUE;
} }
static INT_PTR CALLBACK static INT_PTR CALLBACK
DlgPreferencesProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) DlgPreferencesProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{ {
PPREFERENCES_CONTEXT Context; PPREFERENCES_CONTEXT Context;
switch(uMsg) switch (uMsg)
{
case WM_COMMAND:
{ {
switch(LOWORD(wParam)) case WM_COMMAND:
{
case IDOK:
case IDCANCEL:
{ {
EndDialog(hwndDlg, LOWORD(wParam)); switch (LOWORD(wParam))
break; {
case IDOK:
case IDCANCEL:
{
EndDialog(hwndDlg,
LOWORD(wParam));
break;
}
}
break;
}
case MM_MIXM_LINE_CHANGE:
{
DPRINT("MM_MIXM_LINE_CHANGE\n");
break;
}
case MM_MIXM_CONTROL_CHANGE:
{
DPRINT("MM_MIXM_CONTROL_CHANGE\n");
break;
}
case WM_INITDIALOG:
{
PREFERENCES_FILL_DEVICES FillDevContext;
SetWindowLongPtr(hwndDlg,
DWLP_USER,
(LONG_PTR)lParam);
Context = (PPREFERENCES_CONTEXT)((LONG_PTR)lParam);
Context->hwndDlg = hwndDlg;
Context->Mixer = SndMixerCreate(hwndDlg);
FillDevContext.PrefContext = Context;
FillDevContext.hComboBox = GetDlgItem(hwndDlg,
IDC_MIXERDEVICE);
FillDevContext.Selected = SndMixerGetSelection(Context->Mixer);
SndMixerEnumProducts(Context->Mixer,
FillDeviceComboBox,
&FillDevContext);
return TRUE;
}
case WM_DESTROY:
{
Context = GetDialogData(hwndDlg,
PREFERENCES_CONTEXT);
if (Context->Mixer != NULL)
{
SndMixerDestroy(Context->Mixer);
}
break;
}
case WM_CLOSE:
{
EndDialog(hwndDlg,
IDCANCEL);
break;
} }
}
break;
} }
case MM_MIXM_LINE_CHANGE: return 0;
{
DBG("MM_MIXM_LINE_CHANGE\n");
break;
}
case MM_MIXM_CONTROL_CHANGE:
{
DBG("MM_MIXM_CONTROL_CHANGE\n");
break;
}
case WM_INITDIALOG:
{
PREFERENCES_FILL_DEVICES FillDevContext;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
Context = (PPREFERENCES_CONTEXT)((LONG_PTR)lParam);
Context->hwndDlg = hwndDlg;
Context->Mixer = SndMixerCreate(hwndDlg);
FillDevContext.PrefContext = Context;
FillDevContext.hComboBox = GetDlgItem(hwndDlg, IDC_MIXERDEVICE);
FillDevContext.Selected = SndMixerGetSelection(Context->Mixer);
SndMixerEnumProducts(Context->Mixer,
FillDeviceComboBox,
&FillDevContext);
return TRUE;
}
case WM_DESTROY:
{
Context = GetDialogData(hwndDlg, PREFERENCES_CONTEXT);
if(Context->Mixer != NULL)
{
SndMixerDestroy(Context->Mixer);
}
break;
}
case WM_CLOSE:
{
EndDialog(hwndDlg, IDCANCEL);
break;
}
}
return 0;
} }
/******************************************************************************/ /******************************************************************************/
@ -155,253 +176,285 @@ DeleteMixerWindowControls(PMIXER_WINDOW MixerWindow)
BOOL BOOL
RebuildMixerWindowControls(PMIXER_WINDOW MixerWindow) RebuildMixerWindowControls(PMIXER_WINDOW MixerWindow)
{ {
DeleteMixerWindowControls(MixerWindow); DeleteMixerWindowControls(MixerWindow);
return TRUE; return TRUE;
} }
LRESULT CALLBACK LRESULT CALLBACK
MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) MainWindowProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{ {
PMIXER_WINDOW MixerWindow; PMIXER_WINDOW MixerWindow;
LRESULT Result = 0; LRESULT Result = 0;
switch(uMsg) switch (uMsg)
{
case WM_COMMAND:
{ {
MixerWindow = GetWindowData(hwnd, MIXER_WINDOW); case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_PROPERTIES:
{ {
PREFERENCES_CONTEXT Preferences; MixerWindow = GetWindowData(hwnd,
MIXER_WINDOW);
Preferences.MixerWindow = MixerWindow; switch (LOWORD(wParam))
Preferences.Mixer = NULL; {
case IDC_PROPERTIES:
{
PREFERENCES_CONTEXT Preferences;
if(DialogBoxParam(hAppInstance, Preferences.MixerWindow = MixerWindow;
MAKEINTRESOURCE(IDD_PREFERENCES), Preferences.Mixer = NULL;
hwnd,
DlgPreferencesProc, if (DialogBoxParam(hAppInstance,
(LPARAM)&Preferences) == IDOK) MAKEINTRESOURCE(IDD_PREFERENCES),
{ hwnd,
/* FIXME - update window */ DlgPreferencesProc,
} (LPARAM)&Preferences) == IDOK)
break; {
/* FIXME - update window */
}
break;
}
case IDC_EXIT:
{
PostQuitMessage(0);
break;
}
}
break;
} }
case IDC_EXIT: case MM_MIXM_LINE_CHANGE:
{ {
PostQuitMessage(0); DPRINT("MM_MIXM_LINE_CHANGE\n");
break; break;
} }
}
break;
}
case MM_MIXM_LINE_CHANGE: case MM_MIXM_CONTROL_CHANGE:
{
DBG("MM_MIXM_LINE_CHANGE\n");
break;
}
case MM_MIXM_CONTROL_CHANGE:
{
DBG("MM_MIXM_CONTROL_CHANGE\n");
break;
}
case WM_CREATE:
{
MixerWindow = ((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)MixerWindow);
MixerWindow->hWnd = hwnd;
MixerWindow->hStatusBar = CreateStatusWindow(WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
NULL, hwnd, 0);
if(MixerWindow->hStatusBar != NULL)
{
MixerWindow->Mixer = SndMixerCreate(MixerWindow->hWnd);
if(MixerWindow->Mixer != NULL)
{ {
TCHAR szProduct[MAXPNAMELEN]; DPRINT("MM_MIXM_CONTROL_CHANGE\n");
break;
if(SndMixerGetProductName(MixerWindow->Mixer, szProduct, sizeof(szProduct) / sizeof(szProduct[0])) > 0)
{
SendMessage(MixerWindow->hStatusBar, WM_SETTEXT, 0, (LPARAM)szProduct);
}
if(!RebuildMixerWindowControls(MixerWindow))
{
DBG("Rebuilding mixer window controls failed!\n");
SndMixerDestroy(MixerWindow->Mixer);
Result = -1;
}
} }
else
case WM_CREATE:
{ {
Result = -1; MixerWindow = ((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hwnd,
GWL_USERDATA,
(LONG_PTR)MixerWindow);
MixerWindow->hWnd = hwnd;
MixerWindow->hStatusBar = CreateStatusWindow(WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
NULL,
hwnd,
0);
if (MixerWindow->hStatusBar != NULL)
{
MixerWindow->Mixer = SndMixerCreate(MixerWindow->hWnd);
if (MixerWindow->Mixer != NULL)
{
TCHAR szProduct[MAXPNAMELEN];
if (SndMixerGetProductName(MixerWindow->Mixer,
szProduct,
sizeof(szProduct) / sizeof(szProduct[0])) > 0)
{
SendMessage(MixerWindow->hStatusBar,
WM_SETTEXT,
0,
(LPARAM)szProduct);
}
if (!RebuildMixerWindowControls(MixerWindow))
{
DPRINT("Rebuilding mixer window controls failed!\n");
SndMixerDestroy(MixerWindow->Mixer);
Result = -1;
}
}
else
{
Result = -1;
}
}
else
{
DPRINT("Failed to create status window!\n");
Result = -1;
}
break;
}
case WM_DESTROY:
{
MixerWindow = GetWindowData(hwnd,
MIXER_WINDOW);
if (MixerWindow->Mixer != NULL)
{
SndMixerDestroy(MixerWindow->Mixer);
}
break;
}
case WM_CLOSE:
{
PostQuitMessage(0);
break;
}
default:
{
Result = DefWindowProc(hwnd,
uMsg,
wParam,
lParam);
break;
} }
}
else
{
DBG("Failed to create status window!\n");
Result = -1;
}
break;
} }
case WM_DESTROY: return Result;
{
MixerWindow = GetWindowData(hwnd, MIXER_WINDOW);
if(MixerWindow->Mixer != NULL)
{
SndMixerDestroy(MixerWindow->Mixer);
}
break;
}
case WM_CLOSE:
{
PostQuitMessage(0);
break;
}
default:
{
Result = DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
return Result;
} }
static BOOL static BOOL
RegisterApplicationClasses(VOID) RegisterApplicationClasses(VOID)
{ {
WNDCLASSEX wc; WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX); wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWindowProc; wc.lpfnWndProc = MainWindowProc;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(PMIXER_WINDOW); wc.cbWndExtra = sizeof(PMIXER_WINDOW);
wc.hInstance = hAppInstance; wc.hInstance = hAppInstance;
wc.hIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_MAINAPP)); wc.hIcon = LoadIcon(hAppInstance,
wc.hCursor = LoadCursor(NULL, IDC_ARROW); MAKEINTRESOURCE(IDI_MAINAPP));
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.hCursor = LoadCursor(NULL,
wc.lpszMenuName = NULL; IDC_ARROW);
wc.lpszClassName = SZ_APP_CLASS; wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.hIconSm = NULL; wc.lpszMenuName = NULL;
MainWindowClass = RegisterClassEx(&wc); wc.lpszClassName = SZ_APP_CLASS;
wc.hIconSm = NULL;
MainWindowClass = RegisterClassEx(&wc);
return MainWindowClass != 0; return MainWindowClass != 0;
} }
static VOID static VOID
UnregisterApplicationClasses(VOID) UnregisterApplicationClasses(VOID)
{ {
UnregisterClass(SZ_APP_CLASS, hAppInstance); UnregisterClass(SZ_APP_CLASS,
hAppInstance);
} }
static HWND static HWND
CreateApplicationWindow(VOID) CreateApplicationWindow(VOID)
{ {
LPTSTR lpAppTitle; LPTSTR lpAppTitle;
HWND hWnd; HWND hWnd;
PMIXER_WINDOW MixerWindow = HeapAlloc(hAppHeap, 0, sizeof(MIXER_WINDOW)); PMIXER_WINDOW MixerWindow = HeapAlloc(hAppHeap,
if(MixerWindow == NULL) 0,
{ sizeof(MIXER_WINDOW));
return NULL; if (MixerWindow == NULL)
} {
return NULL;
}
/* load the application title */ /* load the application title */
if(RosAllocAndLoadString(&lpAppTitle, if (AllocAndLoadString(&lpAppTitle,
hAppInstance, hAppInstance,
IDS_SNDVOL32) == 0) IDS_SNDVOL32) == 0)
{ {
lpAppTitle = NULL; lpAppTitle = NULL;
} }
if(mixerGetNumDevs() > 0) if (mixerGetNumDevs() > 0)
{ {
hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT, hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT,
SZ_APP_CLASS, SZ_APP_CLASS,
lpAppTitle, lpAppTitle,
WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL,
LoadMenu(hAppInstance, MAKEINTRESOURCE(IDM_MAINMENU)), LoadMenu(hAppInstance,
hAppInstance, MAKEINTRESOURCE(IDM_MAINMENU)),
MixerWindow); hAppInstance,
} MixerWindow);
else }
{ else
LPTSTR lpErrMessage; {
LPTSTR lpErrMessage;
/* /*
* no mixer devices are available! * no mixer devices are available!
*/ */
hWnd = NULL; hWnd = NULL;
RosAllocAndLoadString(&lpErrMessage, AllocAndLoadString(&lpErrMessage,
hAppInstance, hAppInstance,
IDS_NOMIXERDEVICES); IDS_NOMIXERDEVICES);
MessageBox(NULL, lpErrMessage, lpAppTitle, MB_ICONINFORMATION); MessageBox(NULL,
LocalFree(lpErrMessage); lpErrMessage,
} lpAppTitle,
MB_ICONINFORMATION);
LocalFree(lpErrMessage);
}
if(lpAppTitle != NULL) if (lpAppTitle != NULL)
{ {
LocalFree(lpAppTitle); LocalFree(lpAppTitle);
} }
if(hWnd == NULL) if (hWnd == NULL)
{ {
HeapFree(hAppHeap, 0, MixerWindow); HeapFree(hAppHeap,
} 0,
MixerWindow);
}
return hWnd; return hWnd;
} }
int WINAPI int WINAPI
WinMain(HINSTANCE hInstance, WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, LPSTR lpszCmdLine,
int nCmdShow) int nCmdShow)
{ {
MSG Msg; MSG Msg;
hAppInstance = hInstance; hAppInstance = hInstance;
hAppHeap = GetProcessHeap(); hAppHeap = GetProcessHeap();
InitCommonControls(); InitCommonControls();
if(!RegisterApplicationClasses()) if (!RegisterApplicationClasses())
{ {
DBG("Failed to register application classes (LastError: %d)!\n", GetLastError()); DPRINT("Failed to register application classes (LastError: %d)!\n", GetLastError());
return 1; return 1;
} }
hMainWnd = CreateApplicationWindow(); hMainWnd = CreateApplicationWindow();
if(hMainWnd == NULL) if (hMainWnd == NULL)
{ {
DBG("Failed to creat application window (LastError: %d)!\n", GetLastError()); DPRINT("Failed to creat application window (LastError: %d)!\n", GetLastError());
return 1; return 1;
} }
while(GetMessage(&Msg, NULL, 0, 0)) while (GetMessage(&Msg,
{ NULL,
TranslateMessage(&Msg); 0,
DispatchMessage(&Msg); 0))
} {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
DestroyWindow(hMainWnd); DestroyWindow(hMainWnd);
UnregisterApplicationClasses(); UnregisterApplicationClasses();
return 0; return 0;
} }

View file

@ -28,7 +28,8 @@ extern HANDLE hAppHeap;
#define SZ_APP_CLASS TEXT("Volume Control") #define SZ_APP_CLASS TEXT("Volume Control")
#define DBG DbgPrint("SNDVOL32: %s:%i: ", __FILE__, __LINE__); DbgPrint ULONG DbgPrint(PCH , ...);
#define DPRINT DbgPrint("SNDVOL32: %s:%i: ", __FILE__, __LINE__); DbgPrint
/* /*
@ -74,4 +75,18 @@ BOOL SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOI
INT SndMixerGetDestinationCount(PSND_MIXER Mixer); INT SndMixerGetDestinationCount(PSND_MIXER Mixer);
BOOL SndMixerEnumDestinationLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context); BOOL SndMixerEnumDestinationLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context);
/*
* MISC
*/
INT
AllocAndLoadString(OUT LPWSTR *lpTarget,
IN HINSTANCE hInst,
IN UINT uID);
DWORD
LoadAndFormatString(IN HINSTANCE hInstance,
IN UINT uID,
OUT LPWSTR *lpTarget,
...);
#endif /* __SNDVOL32_H */ #endif /* __SNDVOL32_H */

View file

@ -0,0 +1,19 @@
<module name="sndvol32" type="win32gui" installbase="system32" installname="sndvol32.exe">
<include base="ReactOS">include/wine</include>
<include base="sndvol32">.</include>
<define name="__USE_W32API" />
<define name="UNICODE" />
<define name="_UNICODE" />
<define name="_WIN32_WINNT">0x6501</define>
<library>ntdll</library>
<library>user32</library>
<library>gdi32</library>
<library>kernel32</library>
<library>comctl32</library>
<library>shell32</library>
<library>winmm</library>
<pch>sndvol32.h</pch>
<file>misc.c</file>
<file>mixer.c</file>
<file>sndvol32.c</file>
</module>