mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
very beginning of a reactos volume control application, not really usable yet
svn path=/trunk/; revision=12389
This commit is contained in:
parent
13b05d6081
commit
f5e28a77d1
10 changed files with 999 additions and 0 deletions
6
reactos/subsys/system/sndvol32/.cvsignore
Normal file
6
reactos/subsys/system/sndvol32/.cvsignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.o
|
||||
*.d
|
||||
*.exe
|
||||
*.coff
|
||||
*.sym
|
||||
*.map
|
41
reactos/subsys/system/sndvol32/En.rc
Normal file
41
reactos/subsys/system/sndvol32/En.rc
Normal file
|
@ -0,0 +1,41 @@
|
|||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
IDM_MAINMENU MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "O&ptions"
|
||||
BEGIN
|
||||
MENUITEM "P&roperties", IDC_PROPERTIES
|
||||
MENUITEM "&Advanced Controls", IDC_ADVANCED_CONTROLS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "E&xit", IDC_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&Help Topics", IDC_HELP_TOPICS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About ...", IDC_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_SNDVOL32 "Volume Control"
|
||||
IDS_NOMIXERDEVICES "There are no active mixer devices available! The application will now exit."
|
||||
END
|
||||
|
||||
IDD_PREFERENCES DIALOGEX 0, 0, 224, 250
|
||||
STYLE DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Properties"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "&Mixer device:", -1, 7,8,48,9
|
||||
COMBOBOX IDC_MIXERDEVICE, 55,8,162,80, CBS_DROPDOWNLIST | WS_TABSTOP
|
||||
GROUPBOX "Adjust volume for:", -1, 7,25,211,77
|
||||
PUSHBUTTON "&Playback", IDC_PLAYBACK, 13,43,47,8, BS_AUTORADIOBUTTON
|
||||
PUSHBUTTON "&Recording", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON
|
||||
PUSHBUTTON "&Other:", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED
|
||||
COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED
|
||||
|
||||
PUSHBUTTON "OK", IDOK, 114,226,50,14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 168,226,50,14
|
||||
END
|
23
reactos/subsys/system/sndvol32/Makefile
Normal file
23
reactos/subsys/system/sndvol32/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
# $Id: Makefile,v 1.1 2004/12/29 22:37:13 weiden Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET_TYPE = program
|
||||
|
||||
TARGET_APPTYPE = windows
|
||||
|
||||
TARGET_NAME = sndvol32
|
||||
|
||||
TARGET_INSTALLDIR = system32
|
||||
|
||||
TARGET_CFLAGS = -D__USE_W32API -DUNICODE -D_UNICODE -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501
|
||||
|
||||
TARGET_SDKLIBS = rosrtl.a user32.a kernel32.a ntdll.a
|
||||
|
||||
TARGET_GCCLIBS = winmm msvcrt advapi32 kernel32 comctl32
|
||||
|
||||
TARGET_OBJECTS = $(TARGET_NAME).o mixer.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
24
reactos/subsys/system/sndvol32/manifest.xml
Normal file
24
reactos/subsys/system/sndvol32/manifest.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="X86"
|
||||
name="ReactOS.Sound.Volume.Control"
|
||||
type="win32"
|
||||
/>
|
||||
<description>ReactOS Volume Control</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="X86"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</assembly>
|
||||
|
||||
<!-- EOF -->
|
378
reactos/subsys/system/sndvol32/mixer.c
Normal file
378
reactos/subsys/system/sndvol32/mixer.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* ReactOS Sound Volume Control
|
||||
* Copyright (C) 2004 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: mixer.c,v 1.1 2004/12/29 22:37:13 weiden Exp $
|
||||
*
|
||||
* 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 (~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 = 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, LPMIXERLINE LineInfo, LPMIXERCONTROL *Controls)
|
||||
{
|
||||
if(LineInfo->cControls > 0)
|
||||
{
|
||||
*Controls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, LineInfo->cControls * sizeof(MIXERCONTROL));
|
||||
if(*Controls != NULL)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
DBG("Line control: %ws", (*Controls)[j].szName);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, *Controls);
|
||||
*Controls = NULL;
|
||||
DBG("Failed to get line controls!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Failed to allocate memory for %d line controls!\n", LineInfo->cControls);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL
|
||||
SndMixerQueryConnections(PSND_MIXER Mixer, PSND_MIXER_DESTINATION Line)
|
||||
{
|
||||
UINT i;
|
||||
MIXERLINE LineInfo;
|
||||
BOOL Ret = TRUE;
|
||||
|
||||
LineInfo.cbStruct = sizeof(LineInfo);
|
||||
LineInfo.dwDestination = Line->Info.dwDestination;
|
||||
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;
|
||||
PSND_MIXER_CONNECTION Con;
|
||||
|
||||
if(!SndMixerQueryControls(Mixer, &LineInfo, &Controls))
|
||||
{
|
||||
DBG("Failed to query connection controls\n");
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
Con = HeapAlloc(GetProcessHeap(), 0, sizeof(SND_MIXER_CONNECTION));
|
||||
if(Con != NULL)
|
||||
{
|
||||
Con->Info = LineInfo;
|
||||
Con->Controls = Controls;
|
||||
Con->Next = Line->Connections;
|
||||
Line->Connections = Con;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, Controls);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Failed to get connection information!\n");
|
||||
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 = 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)
|
||||
{
|
||||
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;
|
||||
Mixer->Lines = Line;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Failed to get line information for id %d!\n", i);
|
||||
HeapFree(GetProcessHeap(), 0, Line);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Allocation of SND_MIXER_DEST structure for id %d failed!\n", i);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
SndMixerSelect(PSND_MIXER Mixer, UINT MixerId)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
UINT
|
||||
SndMixerGetSelection(PSND_MIXER Mixer)
|
||||
{
|
||||
return Mixer->MixerId;
|
||||
}
|
||||
|
||||
INT
|
||||
SndMixerGetProductName(PSND_MIXER Mixer, LPTSTR lpBuffer, UINT uSize)
|
||||
{
|
||||
if(Mixer->hmx)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL
|
||||
SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOID Context)
|
||||
{
|
||||
MIXERCAPS Caps;
|
||||
HMIXER hMixer;
|
||||
UINT i;
|
||||
BOOL Ret = TRUE;
|
||||
|
||||
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(!EnumProc(Mixer, i, Caps.szPname, Context))
|
||||
{
|
||||
mixerClose(hMixer);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("Failed to get device capabilities for mixer id %d!\n", i);
|
||||
}
|
||||
mixerClose(hMixer);
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
INT
|
||||
SndMixerGetDestinationCount(PSND_MIXER Mixer)
|
||||
{
|
||||
return (Mixer->hmx ? Mixer->Caps.cDestinations : -1);
|
||||
}
|
||||
|
||||
BOOL
|
||||
SndMixerEnumLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context)
|
||||
{
|
||||
if(Mixer->hmx)
|
||||
{
|
||||
PSND_MIXER_DESTINATION Line;
|
||||
|
||||
for(Line = Mixer->Lines; Line != NULL; Line = Line->Next)
|
||||
{
|
||||
if(!EnumProc(Mixer, &Line->Info, Context))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
24
reactos/subsys/system/sndvol32/resources.h
Normal file
24
reactos/subsys/system/sndvol32/resources.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef __SNDVOL_RESOURCES_H
|
||||
#define __SNDVOL_RESOURCES_H
|
||||
|
||||
#define IDM_MAINMENU 101
|
||||
|
||||
#define IDI_MAINAPP 101
|
||||
|
||||
#define IDC_PROPERTIES 1001
|
||||
#define IDC_ADVANCED_CONTROLS 1002
|
||||
#define IDC_EXIT 1003
|
||||
#define IDC_HELP_TOPICS 1101
|
||||
#define IDC_ABOUT 1102
|
||||
|
||||
#define IDD_PREFERENCES 101
|
||||
#define IDC_MIXERDEVICE 1001
|
||||
#define IDC_PLAYBACK 1002
|
||||
#define IDC_RECORDING 1003
|
||||
#define IDC_OTHER 1004
|
||||
#define IDC_LINE 1005
|
||||
|
||||
#define IDS_SNDVOL32 100
|
||||
#define IDS_NOMIXERDEVICES 101
|
||||
|
||||
#endif /* __SNDVOL_RESOURCES_H */
|
BIN
reactos/subsys/system/sndvol32/resources/sndvol32.ico
Normal file
BIN
reactos/subsys/system/sndvol32/resources/sndvol32.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
407
reactos/subsys/system/sndvol32/sndvol32.c
Normal file
407
reactos/subsys/system/sndvol32/sndvol32.c
Normal file
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* ReactOS Sound Volume Control
|
||||
* Copyright (C) 2004 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: sndvol32.c,v 1.1 2004/12/29 22:37:13 weiden Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Sound Volume Control
|
||||
* FILE: subsys/system/sndvol32/sndvol32.c
|
||||
* PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
|
||||
*/
|
||||
#include "sndvol32.h"
|
||||
|
||||
HINSTANCE hAppInstance;
|
||||
ATOM MainWindowClass;
|
||||
HWND hMainWnd;
|
||||
HANDLE hAppHeap;
|
||||
|
||||
#define GetDialogData(hwndDlg, type) \
|
||||
( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER)
|
||||
#define GetWindowData(hwnd, type) \
|
||||
( P##type )GetWindowLongPtr((hwnd), GWL_USERDATA)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct _PREFERENCES_CONTEXT
|
||||
{
|
||||
PMIXER_WINDOW MixerWindow;
|
||||
PSND_MIXER Mixer;
|
||||
HWND hwndDlg;
|
||||
} PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT;
|
||||
|
||||
typedef struct _PREFERENCES_FILL_DEVICES
|
||||
{
|
||||
PPREFERENCES_CONTEXT PrefContext;
|
||||
HWND hComboBox;
|
||||
UINT Selected;
|
||||
} PREFERENCES_FILL_DEVICES, *PPREFERENCES_FILL_DEVICES;
|
||||
|
||||
static BOOL CALLBACK
|
||||
FillDeviceComboBox(PSND_MIXER Mixer, UINT Id, LPCTSTR ProductName, PVOID Context)
|
||||
{
|
||||
LRESULT lres;
|
||||
PPREFERENCES_FILL_DEVICES FillContext = (PPREFERENCES_FILL_DEVICES)Context;
|
||||
|
||||
lres = SendMessage(FillContext->hComboBox, CB_ADDSTRING, 0, (LPARAM)ProductName);
|
||||
if(lres != CB_ERR)
|
||||
{
|
||||
/* save the index so we don't screw stuff when the combobox is sorted... */
|
||||
SendMessage(FillContext->hComboBox, CB_SETITEMDATA, (WPARAM)lres, Id);
|
||||
|
||||
if(Id == FillContext->Selected)
|
||||
{
|
||||
SendMessage(FillContext->hComboBox, CB_SETCURSEL, (WPARAM)lres, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK
|
||||
DlgPreferencesProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PPREFERENCES_CONTEXT Context;
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
case IDCANCEL:
|
||||
{
|
||||
EndDialog(hwndDlg, LOWORD(wParam));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MM_MIXM_LINE_CHANGE:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static VOID
|
||||
DeleteMixerWindowControls(PMIXER_WINDOW MixerWindow)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL
|
||||
RebuildMixerWindowControls(PMIXER_WINDOW MixerWindow)
|
||||
{
|
||||
DeleteMixerWindowControls(MixerWindow);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PMIXER_WINDOW MixerWindow;
|
||||
LRESULT Result = 0;
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
MixerWindow = GetWindowData(hwnd, MIXER_WINDOW);
|
||||
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_PROPERTIES:
|
||||
{
|
||||
PREFERENCES_CONTEXT Preferences;
|
||||
|
||||
Preferences.MixerWindow = MixerWindow;
|
||||
Preferences.Mixer = NULL;
|
||||
|
||||
if(DialogBoxParam(hAppInstance,
|
||||
MAKEINTRESOURCE(IDD_PREFERENCES),
|
||||
hwnd,
|
||||
DlgPreferencesProc,
|
||||
(LPARAM)&Preferences) == IDOK)
|
||||
{
|
||||
/* FIXME - update window */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IDC_EXIT:
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MM_MIXM_LINE_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];
|
||||
|
||||
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
|
||||
{
|
||||
Result = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG("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);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
RegisterApplicationClasses(VOID)
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = MainWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = sizeof(PMIXER_WINDOW);
|
||||
wc.hInstance = hAppInstance;
|
||||
wc.hIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_MAINAPP));
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = SZ_APP_CLASS;
|
||||
wc.hIconSm = NULL;
|
||||
MainWindowClass = RegisterClassEx(&wc);
|
||||
|
||||
return MainWindowClass != 0;
|
||||
}
|
||||
|
||||
static VOID
|
||||
UnregisterApplicationClasses(VOID)
|
||||
{
|
||||
UnregisterClass(SZ_APP_CLASS, hAppInstance);
|
||||
}
|
||||
|
||||
static HWND
|
||||
CreateApplicationWindow(VOID)
|
||||
{
|
||||
LPTSTR lpAppTitle;
|
||||
HWND hWnd;
|
||||
|
||||
PMIXER_WINDOW MixerWindow = HeapAlloc(hAppHeap, 0, sizeof(MIXER_WINDOW));
|
||||
if(MixerWindow == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* load the application title */
|
||||
if(RosAllocAndLoadString(&lpAppTitle,
|
||||
hAppInstance,
|
||||
IDS_SNDVOL32) == 0)
|
||||
{
|
||||
lpAppTitle = NULL;
|
||||
}
|
||||
|
||||
if(mixerGetNumDevs() > 0)
|
||||
{
|
||||
hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT,
|
||||
SZ_APP_CLASS,
|
||||
lpAppTitle,
|
||||
WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
NULL,
|
||||
LoadMenu(hAppInstance, MAKEINTRESOURCE(IDM_MAINMENU)),
|
||||
hAppInstance,
|
||||
MixerWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
LPTSTR lpErrMessage;
|
||||
|
||||
/*
|
||||
* no mixer devices are available!
|
||||
*/
|
||||
|
||||
hWnd = NULL;
|
||||
RosAllocAndLoadString(&lpErrMessage,
|
||||
hAppInstance,
|
||||
IDS_NOMIXERDEVICES);
|
||||
MessageBox(NULL, lpErrMessage, lpAppTitle, MB_ICONINFORMATION);
|
||||
LocalFree(lpErrMessage);
|
||||
}
|
||||
|
||||
if(lpAppTitle != NULL)
|
||||
{
|
||||
LocalFree(lpAppTitle);
|
||||
}
|
||||
|
||||
if(hWnd == NULL)
|
||||
{
|
||||
HeapFree(hAppHeap, 0, MixerWindow);
|
||||
}
|
||||
|
||||
return hWnd;
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpszCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
MSG Msg;
|
||||
|
||||
hAppInstance = hInstance;
|
||||
hAppHeap = GetProcessHeap();
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
if(!RegisterApplicationClasses())
|
||||
{
|
||||
DBG("Failed to register application classes (LastError: %d)!\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
hMainWnd = CreateApplicationWindow();
|
||||
if(hMainWnd == NULL)
|
||||
{
|
||||
DBG("Failed to creat application window (LastError: %d)!\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(GetMessage(&Msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&Msg);
|
||||
DispatchMessage(&Msg);
|
||||
}
|
||||
|
||||
DestroyWindow(hMainWnd);
|
||||
|
||||
UnregisterApplicationClasses();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
78
reactos/subsys/system/sndvol32/sndvol32.h
Normal file
78
reactos/subsys/system/sndvol32/sndvol32.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
#ifndef __SNDVOL32_H
|
||||
#define __SNDVOL32_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <string.h>
|
||||
#include <rosrtl/resstr.h>
|
||||
#include "resources.h"
|
||||
|
||||
typedef struct _MIXER_WINDOW
|
||||
{
|
||||
HWND hWnd;
|
||||
HWND hStatusBar;
|
||||
struct _SND_MIXER *Mixer;
|
||||
UINT SelectedLine;
|
||||
} MIXER_WINDOW, *PMIXER_WINDOW;
|
||||
|
||||
LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BOOL RebuildMixerWindowControls(PMIXER_WINDOW MixerWindow);
|
||||
|
||||
extern HINSTANCE hAppInstance;
|
||||
extern ATOM MainWindowClass;
|
||||
extern HWND hMainWnd;
|
||||
extern HANDLE hAppHeap;
|
||||
|
||||
#define SZ_APP_CLASS TEXT("Volume Control")
|
||||
|
||||
#define DBG DbgPrint("SNDVOL32: %s:%i: ", __FILE__, __LINE__); DbgPrint
|
||||
|
||||
|
||||
/*
|
||||
* MIXER
|
||||
*/
|
||||
|
||||
typedef struct _SND_MIXER_CONNECTION
|
||||
{
|
||||
struct _SND_MIXER_CONNECTION *Next;
|
||||
MIXERLINE Info;
|
||||
LPMIXERCONTROL Controls;
|
||||
} SND_MIXER_CONNECTION, *PSND_MIXER_CONNECTION;
|
||||
|
||||
|
||||
typedef struct _SND_MIXER_DESTINATION
|
||||
{
|
||||
struct _SND_MIXER_DESTINATION *Next;
|
||||
MIXERLINE Info;
|
||||
LPMIXERCONTROL Controls;
|
||||
PSND_MIXER_CONNECTION Connections;
|
||||
} SND_MIXER_DESTINATION, *PSND_MIXER_DESTINATION;
|
||||
|
||||
typedef struct _SND_MIXER
|
||||
{
|
||||
UINT MixersCount;
|
||||
HWND hWndNotification;
|
||||
UINT MixerId;
|
||||
HMIXER hmx;
|
||||
MIXERCAPS Caps;
|
||||
PSND_MIXER_DESTINATION Lines;
|
||||
} SND_MIXER, *PSND_MIXER;
|
||||
|
||||
typedef BOOL (CALLBACK *PFNSNDMIXENUMLINES)(PSND_MIXER Mixer, LPMIXERLINE Line, PVOID Context);
|
||||
typedef BOOL (CALLBACK *PFNSNDMIXENUMPRODUCTS)(PSND_MIXER Mixer, UINT Id, LPCTSTR ProductName, PVOID Context);
|
||||
|
||||
PSND_MIXER SndMixerCreate(HWND hWndNotification);
|
||||
VOID SndMixerDestroy(PSND_MIXER Mixer);
|
||||
VOID SndMixerClose(PSND_MIXER Mixer);
|
||||
BOOL SndMixerSelect(PSND_MIXER Mixer, UINT MixerId);
|
||||
UINT SndMixerGetSelection(PSND_MIXER Mixer);
|
||||
INT SndMixerGetProductName(PSND_MIXER Mixer, LPTSTR lpBuffer, UINT uSize);
|
||||
BOOL SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOID Context);
|
||||
INT SndMixerGetDestinationCount(PSND_MIXER Mixer);
|
||||
BOOL SndMixerEnumDestinationLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context);
|
||||
|
||||
#endif /* __SNDVOL32_H */
|
18
reactos/subsys/system/sndvol32/sndvol32.rc
Normal file
18
reactos/subsys/system/sndvol32/sndvol32.rc
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* $Id: sndvol32.rc,v 1.1 2004/12/29 22:37:13 weiden Exp $ */
|
||||
|
||||
#include <defines.h>
|
||||
#include "resources.h"
|
||||
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Sound Volume Control\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "sndvol32\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "sndvol32.exe\0"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
1 24 DISCARDABLE "manifest.xml"
|
||||
|
||||
IDI_MAINAPP ICON DISCARDABLE resources/sndvol32.ico
|
||||
|
||||
#include "En.rc"
|
||||
|
Loading…
Reference in a new issue