Commit in reactos/subsys/system/sndvol32 on MAIN
.cvsignore+6added 1.1
En.rc+41added 1.1
Makefile+23added 1.1
manifest.xml+24added 1.1
mixer.c+378added 1.1
resources.h+24added 1.1
sndvol32.c+407added 1.1
sndvol32.h+78added 1.1
sndvol32.rc+18added 1.1
resources/sndvol32.ico[binary]added 1.1
+999
10 added files
very beginning of a reactos volume control application, not really usable yet

reactos/subsys/system/sndvol32
.cvsignore added at 1.1
diff -N .cvsignore
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ .cvsignore	29 Dec 2004 22:37:13 -0000	1.1
@@ -0,0 +1,6 @@
+*.o
+*.d
+*.exe
+*.coff
+*.sym
+*.map
\ No newline at end of file

reactos/subsys/system/sndvol32
En.rc added at 1.1
diff -N En.rc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ En.rc	29 Dec 2004 22:37:13 -0000	1.1
@@ -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

reactos/subsys/system/sndvol32
Makefile added at 1.1
diff -N Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile	29 Dec 2004 22:37:13 -0000	1.1
@@ -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

reactos/subsys/system/sndvol32
manifest.xml added at 1.1
diff -N manifest.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ manifest.xml	29 Dec 2004 22:37:13 -0000	1.1
@@ -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 -->

reactos/subsys/system/sndvol32
mixer.c added at 1.1
diff -N mixer.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mixer.c	29 Dec 2004 22:37:13 -0000	1.1
@@ -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;
+}
+

reactos/subsys/system/sndvol32
resources.h added at 1.1
diff -N resources.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ resources.h	29 Dec 2004 22:37:13 -0000	1.1
@@ -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 */

reactos/subsys/system/sndvol32
sndvol32.c added at 1.1
diff -N sndvol32.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sndvol32.c	29 Dec 2004 22:37:13 -0000	1.1
@@ -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;
+}
+

reactos/subsys/system/sndvol32
sndvol32.h added at 1.1
diff -N sndvol32.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sndvol32.h	29 Dec 2004 22:37:13 -0000	1.1
@@ -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 */

reactos/subsys/system/sndvol32
sndvol32.rc added at 1.1
diff -N sndvol32.rc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sndvol32.rc	29 Dec 2004 22:37:13 -0000	1.1
@@ -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"
+
CVSspam 0.2.8