ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sndvol32.c
Go to the documentation of this file.
00001 /*
00002  * ReactOS Sound Volume Control
00003  * Copyright (C) 2004-2005 Thomas Weidenmueller
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 /* $Id: sndvol32.c 51523 2011-05-01 12:53:10Z rharabien $
00020  *
00021  * COPYRIGHT:   See COPYING in the top level directory
00022  * PROJECT:     ReactOS Sound Volume Control
00023  * FILE:        subsys/system/sndvol32/sndvol32.c
00024  * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
00025  */
00026 #include "sndvol32.h"
00027 
00028 HINSTANCE hAppInstance;
00029 ATOM MainWindowClass;
00030 HWND hMainWnd;
00031 HANDLE hAppHeap;
00032 LPTSTR lpAppTitle;
00033 PREFERENCES_CONTEXT Preferences;
00034 
00035 #define GetDialogData(hwndDlg, type) \
00036     ( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER)
00037 #define GetWindowData(hwnd, type) \
00038     ( P##type )GetWindowLongPtr((hwnd), GWL_USERDATA)
00039 
00040 /******************************************************************************/
00041 
00042 
00043 
00044 typedef struct _PREFERENCES_FILL_DEVICES
00045 {
00046     PPREFERENCES_CONTEXT PrefContext;
00047     HWND hComboBox;
00048     UINT Selected;
00049 } PREFERENCES_FILL_DEVICES, *PPREFERENCES_FILL_DEVICES;
00050 
00051 static BOOL CALLBACK
00052 FillDeviceComboBox(PSND_MIXER Mixer,
00053                    UINT Id,
00054                    LPCTSTR ProductName,
00055                    PVOID Context)
00056 {
00057     LRESULT lres;
00058     PPREFERENCES_FILL_DEVICES FillContext = (PPREFERENCES_FILL_DEVICES)Context;
00059 
00060     UNREFERENCED_PARAMETER(Mixer);
00061 
00062     lres = SendMessage(FillContext->hComboBox,
00063                        CB_ADDSTRING,
00064                        0,
00065                        (LPARAM)ProductName);
00066     if (lres != CB_ERR)
00067     {
00068         /* save the index so we don't screw stuff when the combobox is sorted... */
00069         SendMessage(FillContext->hComboBox,
00070                     CB_SETITEMDATA,
00071                     (WPARAM)lres,
00072                     Id);
00073 
00074         if (Id == FillContext->Selected)
00075         {
00076             SendMessage(FillContext->hComboBox,
00077                         CB_SETCURSEL,
00078                         (WPARAM)lres,
00079                         0);
00080         }
00081     }
00082 
00083     return TRUE;
00084 }
00085 
00086 static BOOL CALLBACK
00087 PrefDlgAddLine(PSND_MIXER Mixer,
00088                LPMIXERLINE Line,
00089                UINT DisplayControls,
00090                PVOID Context)
00091 {
00092     PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context;
00093 
00094     UNREFERENCED_PARAMETER(Mixer);
00095     UNREFERENCED_PARAMETER(DisplayControls);
00096 
00097     switch (Line->dwComponentType)
00098     {
00099         case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
00100             if (PrefContext->PlaybackID == (DWORD)-1)
00101             {
00102                 PrefContext->PlaybackID = Line->dwLineID;
00103 
00104                 if (PrefContext->SelectedLine == (DWORD)-1)
00105                 {
00106                     PrefContext->SelectedLine = Line->dwLineID;
00107                 }
00108             }
00109             else
00110                 goto AddToOthersLines;
00111 
00112             break;
00113 
00114         case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
00115             if (PrefContext->RecordingID == (DWORD)-1)
00116             {
00117                 PrefContext->RecordingID = Line->dwLineID;
00118 
00119                 if (PrefContext->SelectedLine == (DWORD)-1)
00120                 {
00121                     PrefContext->SelectedLine = Line->dwLineID;
00122                 }
00123             }
00124             else
00125                 goto AddToOthersLines;
00126 
00127             break;
00128 
00129         default:
00130         {
00131             LRESULT lres;
00132             HWND hwndCbOthers;
00133 
00134             if (PrefContext->SelectedLine == (DWORD)-1)
00135             {
00136                 PrefContext->SelectedLine = Line->dwLineID;
00137             }
00138 
00139 AddToOthersLines:
00140             hwndCbOthers = GetDlgItem(PrefContext->hwndDlg,
00141                                       IDC_LINE);
00142 
00143             lres = SendMessage(hwndCbOthers,
00144                                CB_ADDSTRING,
00145                                0,
00146                                (LPARAM)Line->szName);
00147             if (lres != CB_ERR)
00148             {
00149                 SendMessage(hwndCbOthers,
00150                             CB_SETITEMDATA,
00151                             (WPARAM)lres,
00152                             Line->dwLineID);
00153 
00154                 PrefContext->OtherLines++;
00155             }
00156             break;
00157         }
00158     }
00159 
00160     return TRUE;
00161 }
00162 
00163 static BOOL CALLBACK
00164 PrefDlgAddConnection(PSND_MIXER Mixer,
00165                      DWORD LineID,
00166                      LPMIXERLINE Line,
00167                      PVOID Context)
00168 {
00169     PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context;
00170     HWND hwndControls;
00171     LVITEM lvi;
00172     UINT i;
00173 
00174     UNREFERENCED_PARAMETER(Mixer);
00175     UNREFERENCED_PARAMETER(LineID);
00176 
00177     if (Line->cControls != 0)
00178     {
00179         hwndControls = GetDlgItem(PrefContext->hwndDlg,
00180                                   IDC_CONTROLS);
00181 
00182         lvi.mask = LVIF_TEXT | LVIF_PARAM;
00183         lvi.iItem = PrefContext->tmp++;
00184         lvi.iSubItem = 0;
00185         lvi.pszText = Line->szName;
00186         lvi.lParam = (LPARAM)Line->dwSource;
00187 
00188         i = SendMessage(hwndControls,
00189                         LVM_INSERTITEM,
00190                         0,
00191                         (LPARAM)&lvi);
00192         if (i != (UINT)-1)
00193         {
00194             TCHAR LineName[MIXER_LONG_NAME_CHARS];
00195             DWORD Flags;
00196             BOOL SelLine = FALSE;
00197 
00198             if (SndMixerGetLineName(PrefContext->Mixer,
00199                                     PrefContext->SelectedLine,
00200                                     LineName,
00201                                     MIXER_LONG_NAME_CHARS,
00202                                     TRUE) == -1)
00203             {
00204                 LineName[0] = TEXT('\0');
00205             }
00206 
00207             if (ReadLineConfig(PrefContext->DeviceName,
00208                                LineName,
00209                                Line->szName,
00210                                &Flags))
00211             {
00212                 if (Flags != 0x4)
00213                 {
00214                     SelLine = TRUE;
00215                 }
00216             }
00217 
00218             ListView_SetCheckState(hwndControls,
00219                                    i,
00220                                    SelLine);
00221         }
00222     }
00223 
00224     return TRUE;
00225 }
00226 
00227 static VOID
00228 UpdatePrefDlgControls(PPREFERENCES_CONTEXT Context,
00229                       DWORD LineID)
00230 {
00231     INT OldID, MixerID = 0;
00232     INT DeviceCbIndex;
00233 
00234     /* select the mixer */
00235     DeviceCbIndex = SendDlgItemMessage(Context->hwndDlg,
00236                                        IDC_MIXERDEVICE,
00237                                        CB_GETCURSEL,
00238                                        0,
00239                                        0);
00240     if (DeviceCbIndex != CB_ERR)
00241     {
00242         MixerID = SendDlgItemMessage(Context->hwndDlg,
00243                                      IDC_MIXERDEVICE,
00244                                      CB_GETITEMDATA,
00245                                      DeviceCbIndex,
00246                                      0);
00247         if (MixerID == CB_ERR)
00248         {
00249             MixerID = 0;
00250         }
00251     }
00252 
00253     OldID = Context->Selected;
00254     if (MixerID != OldID &&
00255         SndMixerSelect(Context->Mixer,
00256                        MixerID))
00257     {
00258         Context->Selected = SndMixerGetSelection(Context->Mixer);
00259 
00260         /* update the controls */
00261         Context->PlaybackID = (DWORD)-1;
00262         Context->RecordingID = (DWORD)-1;
00263         Context->OtherLines = 0;
00264         Context->SelectedLine = (DWORD)-1;
00265 
00266         SndMixerGetProductName(Context->Mixer,
00267                                Context->DeviceName,
00268                                sizeof(Context->DeviceName) / sizeof(Context->DeviceName[0]));
00269 
00270         if (SndMixerEnumLines(Context->Mixer,
00271                               PrefDlgAddLine,
00272                               Context))
00273         {
00274             UINT SelBox = 0;
00275 
00276             /* enable/disable controls and make default selection */
00277             EnableWindow(GetDlgItem(Context->hwndDlg,
00278                                     IDC_PLAYBACK),
00279                          Context->PlaybackID != (DWORD)-1);
00280             CheckDlgButton(Context->hwndDlg,
00281                            IDC_PLAYBACK,
00282                            (Context->PlaybackID != (DWORD)-1 && SelBox++ == 0) ?
00283                                BST_CHECKED : BST_UNCHECKED);
00284 
00285             EnableWindow(GetDlgItem(Context->hwndDlg,
00286                                     IDC_RECORDING),
00287                          Context->RecordingID != (DWORD)-1);
00288             CheckDlgButton(Context->hwndDlg,
00289                            IDC_RECORDING,
00290                            (Context->RecordingID != (DWORD)-1 && SelBox++ == 0) ?
00291                                BST_CHECKED : BST_UNCHECKED);
00292 
00293             if (Context->OtherLines != 0)
00294             {
00295                 /* select the first item in the other lines combo box by default */
00296                 SendDlgItemMessage(Context->hwndDlg,
00297                                    IDC_LINE,
00298                                    CB_SETCURSEL,
00299                                    0,
00300                                    0);
00301             }
00302             EnableWindow(GetDlgItem(Context->hwndDlg,
00303                                     IDC_LINE),
00304                          FALSE);
00305             EnableWindow(GetDlgItem(Context->hwndDlg,
00306                                     IDC_OTHER),
00307                          Context->OtherLines != 0);
00308             CheckDlgButton(Context->hwndDlg,
00309                            IDC_LINE,
00310                            (Context->OtherLines != 0 && SelBox++ == 0) ?
00311                                BST_CHECKED : BST_UNCHECKED);
00312 
00313             /* disable the OK button if the device doesn't have any lines */
00314             EnableWindow(GetDlgItem(Context->hwndDlg,
00315                                     IDOK),
00316                          Context->PlaybackID != (DWORD)-1 ||
00317                          Context->RecordingID != (DWORD)-1 ||
00318                          Context->OtherLines != 0);
00319 
00320             LineID = Context->SelectedLine;
00321         }
00322     }
00323 
00324     /* update the line sources list */
00325     if ((MixerID != OldID && Context->SelectedLine != (DWORD)-1) ||
00326         (Context->SelectedLine != LineID && LineID != (DWORD)-1))
00327     {
00328         Context->SelectedLine = LineID;
00329 
00330         (void)ListView_DeleteAllItems(GetDlgItem(Context->hwndDlg,
00331                                       IDC_CONTROLS));
00332 
00333         Context->tmp = 0;
00334         SndMixerEnumConnections(Context->Mixer,
00335                                 LineID,
00336                                 PrefDlgAddConnection,
00337                                 Context);
00338     }
00339 }
00340 
00341 static 
00342 VOID
00343 WriteLineSettings(PPREFERENCES_CONTEXT Context, HWND hwndDlg)
00344 {
00345     HWND hwndControls;
00346     INT Count, Index;
00347     WCHAR LineName[MIXER_LONG_NAME_CHARS];
00348     WCHAR DestinationName[MIXER_LONG_NAME_CHARS];
00349     DWORD Flags;
00350     PSNDVOL_REG_LINESTATE LineStates;
00351 
00352     /* get list view */
00353     hwndControls = GetDlgItem(hwndDlg, IDC_CONTROLS);
00354 
00355     /* get list item count */
00356     Count = ListView_GetItemCount(hwndControls);
00357 
00358     /* sanity check */
00359     assert(Count);
00360 
00361     if (SndMixerGetLineName(Context->Mixer, Context->SelectedLine, DestinationName, MIXER_LONG_NAME_CHARS, TRUE) == -1)
00362     {
00363         /* failed to get destination line name */
00364         return;
00365     }
00366 
00367     /* allocate line states array */
00368     LineStates = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SNDVOL_REG_LINESTATE) * Count);
00369     if (LineStates == NULL)
00370     {
00371         /* failed to allocate line states array */
00372         return;
00373     }
00374 
00375 
00376     for(Index = 0; Index < Count; Index++)
00377     {
00378         /* set to empty */
00379         LineName[0] = L'\0';
00380 
00381         /* get item text */
00382         ListView_GetItemText(hwndControls, Index, 0, LineName, MIXER_LONG_NAME_CHARS);
00383 
00384         /* make sure it is null terminated */
00385         LineName[MIXER_LONG_NAME_CHARS-1] = L'\0';
00386 
00387         /* get check state */
00388         Flags = (ListView_GetCheckState(hwndControls, Index) == 0 ? 0x4 : 0);
00389 
00390         /* copy line name */
00391         wcscpy(LineStates[Index].LineName, LineName);
00392 
00393         /* store flags */
00394         LineStates[Index].Flags = Flags;
00395     }
00396 
00397     /* now write the line config */
00398     WriteLineConfig(Context->DeviceName, DestinationName, LineStates, sizeof(SNDVOL_REG_LINESTATE) * Count);
00399 
00400     /* free line states */
00401     HeapFree(GetProcessHeap(), 0, LineStates);
00402 }
00403 
00404 static INT_PTR CALLBACK
00405 DlgPreferencesProc(HWND hwndDlg,
00406                    UINT uMsg,
00407                    WPARAM wParam,
00408                    LPARAM lParam)
00409 {
00410     PPREFERENCES_CONTEXT Context;
00411 
00412     switch (uMsg)
00413     {
00414         case WM_COMMAND:
00415         {
00416             Context = GetDialogData(hwndDlg,
00417                                     PREFERENCES_CONTEXT);
00418             switch (LOWORD(wParam))
00419             {
00420                 case IDC_MIXERDEVICE:
00421                 {
00422                     if (HIWORD(wParam) == CBN_SELCHANGE)
00423                     {
00424                         UpdatePrefDlgControls(Context,
00425                                               (DWORD)-1);
00426                     }
00427                     break;
00428                 }
00429 
00430                 case IDC_LINE:
00431                 {
00432                     if (HIWORD(wParam) == CBN_SELCHANGE)
00433                     {
00434                         INT LineID;
00435                         INT Index;
00436 
00437                         Index = SendDlgItemMessage(hwndDlg,
00438                                                    IDC_LINE,
00439                                                    CB_GETCURSEL,
00440                                                    0,
00441                                                    0);
00442                         if (Index != CB_ERR)
00443                         {
00444                             LineID = SendDlgItemMessage(hwndDlg,
00445                                                         IDC_LINE,
00446                                                         CB_GETITEMDATA,
00447                                                         Index,
00448                                                         0);
00449                             if (LineID != CB_ERR)
00450                             {
00451                                 UpdatePrefDlgControls(Context,
00452                                                       LineID);
00453                             }
00454                         }
00455                     }
00456                     break;
00457                 }
00458 
00459                 case IDC_PLAYBACK:
00460                 {
00461                     UpdatePrefDlgControls(Context,
00462                                           Context->PlaybackID);
00463                     EnableWindow(GetDlgItem(hwndDlg,
00464                                             IDC_LINE),
00465                                  FALSE);
00466                     break;
00467                 }
00468 
00469                 case IDC_RECORDING:
00470                 {
00471                     UpdatePrefDlgControls(Context,
00472                                           Context->RecordingID);
00473                     EnableWindow(GetDlgItem(hwndDlg,
00474                                             IDC_LINE),
00475                                  FALSE);
00476                     break;
00477                 }
00478 
00479                 case IDC_OTHER:
00480                 {
00481                     INT LineCbIndex;
00482                     INT LineID;
00483 
00484                     EnableWindow(GetDlgItem(hwndDlg,
00485                                             IDC_LINE),
00486                                  TRUE);
00487 
00488                     LineCbIndex = SendDlgItemMessage(hwndDlg,
00489                                                      IDC_LINE,
00490                                                      CB_GETCURSEL,
00491                                                      0,
00492                                                      0);
00493                     if (LineCbIndex != CB_ERR)
00494                     {
00495                         LineID = SendDlgItemMessage(hwndDlg,
00496                                                     IDC_LINE,
00497                                                     CB_GETITEMDATA,
00498                                                     LineCbIndex,
00499                                                     0);
00500                         if (LineID != CB_ERR)
00501                         {
00502                             UpdatePrefDlgControls(Context,
00503                                                   LineID);
00504                         }
00505                     }
00506                     break;
00507                 }
00508 
00509                 case IDOK:
00510                 {
00511                     /* write line settings */
00512                     WriteLineSettings(Context, hwndDlg);
00513 
00514                     /* fall through */
00515                 }
00516                 case IDCANCEL:
00517                 {
00518                     EndDialog(hwndDlg,
00519                               LOWORD(wParam));
00520                     break;
00521                 }
00522             }
00523             break;
00524         }
00525 
00526         case WM_INITDIALOG:
00527         {
00528             PREFERENCES_FILL_DEVICES FillDevContext;
00529             LVCOLUMN lvc;
00530             RECT rcClient;
00531             HWND hwndControls;
00532 
00533             SetWindowLongPtr(hwndDlg,
00534                              DWLP_USER,
00535                              (LONG_PTR)lParam);
00536             Context = (PPREFERENCES_CONTEXT)((LONG_PTR)lParam);
00537             Context->hwndDlg = hwndDlg;
00538             Context->Mixer = SndMixerCreate(hwndDlg);
00539             Context->Selected = (UINT)-1;
00540 
00541             FillDevContext.PrefContext = Context;
00542             FillDevContext.hComboBox = GetDlgItem(hwndDlg,
00543                                                   IDC_MIXERDEVICE);
00544             FillDevContext.Selected = SndMixerGetSelection(Context->Mixer);
00545             SndMixerEnumProducts(Context->Mixer,
00546                                  FillDeviceComboBox,
00547                                  &FillDevContext);
00548 
00549             /* initialize the list view control */
00550             hwndControls = GetDlgItem(hwndDlg,
00551                                       IDC_CONTROLS);
00552             (void)ListView_SetExtendedListViewStyle(hwndControls,
00553                                                     LVS_EX_CHECKBOXES);
00554 
00555             GetClientRect(hwndControls,
00556                           &rcClient);
00557             lvc.mask = LVCF_TEXT | LVCF_WIDTH;
00558             lvc.pszText = TEXT("");
00559             lvc.cx = rcClient.right;
00560             SendMessage(hwndControls,
00561                         LVM_INSERTCOLUMN,
00562                         0,
00563                         (LPARAM)&lvc);
00564 
00565             /* update all controls */
00566             UpdatePrefDlgControls(Context,
00567                                   (DWORD)Context->SelectedLine);
00568             return TRUE;
00569         }
00570 
00571         case WM_CLOSE:
00572         {
00573             EndDialog(hwndDlg,
00574                       IDCANCEL);
00575             break;
00576         }
00577         
00578         case WM_SYSCOLORCHANGE:
00579         {
00580             HWND hwndControls;
00581             
00582             /* Forward WM_SYSCOLORCHANGE */
00583             hwndControls = GetDlgItem(hwndDlg, IDC_CONTROLS);
00584             SendMessage(hwndControls, WM_SYSCOLORCHANGE, 0, 0);
00585             break;
00586         }
00587     }
00588 
00589     return 0;
00590 }
00591 
00592 
00593 /******************************************************************************/
00594 
00595 static VOID
00596 DeleteMixerWindowControls(PMIXER_WINDOW MixerWindow)
00597 {
00598     DWORD Index;
00599 
00600     for(Index = 0; Index < MixerWindow->WindowCount; Index++)
00601     {
00602         /* destroys the window */
00603         DestroyWindow(MixerWindow->Window[Index]);
00604     }
00605 
00606     /* free memory */
00607     HeapFree(GetProcessHeap(), 0, MixerWindow->Window);
00608 
00609     /* set to null */
00610     MixerWindow->Window = NULL;
00611     MixerWindow->WindowCount = 0;
00612 }
00613 
00614 static BOOL
00615 RebuildMixerWindowControls(PPREFERENCES_CONTEXT PrefContext)
00616 {
00617     /* delete existing mixer controls */
00618     DeleteMixerWindowControls(PrefContext->MixerWindow);
00619 
00620     /* load new mixer controls */
00621     LoadDialogCtrls(PrefContext);
00622 
00623     return TRUE;
00624 }
00625 
00626 static
00627 BOOL
00628 CALLBACK
00629 SetVolumeCallback(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, PVOID Ctx)
00630 {
00631     UINT ControlCount = 0, Index;
00632     LPMIXERCONTROL Control = NULL;
00633     MIXERCONTROLDETAILS_UNSIGNED uDetails;
00634     MIXERCONTROLDETAILS_BOOLEAN bDetails;
00635     PSET_VOLUME_CONTEXT Context = (PSET_VOLUME_CONTEXT)Ctx;
00636 
00637     /* check if the line name is equal */
00638     if (wcsicmp(Line->szName, Context->LineName))
00639     {
00640         /* it is not */
00641         return TRUE;
00642     }
00643 
00644     /* query controls */
00645     if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) == FALSE)
00646     {
00647         /* failed to query for controls */
00648         return FALSE;
00649     }
00650 
00651     /* now go through all controls and compare control ids */
00652     for(Index = 0; Index < ControlCount; Index++)
00653     {
00654         if (Context->bVertical)
00655         {
00656             if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_FADER)
00657             {
00658                 /* FIXME: give me granularity */
00659                 DWORD Step = 0x10000 / 5;
00660 
00661                 /* set up details */
00662                 uDetails.dwValue = 0x10000 - Step * Context->SliderPos;
00663 
00664                 /* set volume */
00665                 SndMixerSetVolumeControlDetails(Preferences.MixerWindow->Mixer, Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&uDetails);
00666 
00667                 /* done */
00668                 break;
00669             }
00670         }
00671         else if (Context->bSwitch)
00672         {
00673             if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_SWITCH)
00674             {
00675                 /* set up details */
00676                 bDetails.fValue = Context->SliderPos;
00677 
00678                 /* set volume */
00679                 SndMixerSetVolumeControlDetails(Preferences.MixerWindow->Mixer, Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&bDetails);
00680 
00681                 /* done */
00682                 break;
00683             }
00684         }
00685         else
00686         {
00687             /* FIXME: implement left - right channel switch support */
00688             assert(0);
00689         }
00690     }
00691 
00692     /* free controls */
00693     HeapFree(GetProcessHeap(), 0, Control);
00694 
00695 
00696     /* done */
00697     return TRUE;
00698 }
00699 
00700 static
00701 BOOL
00702 CALLBACK
00703 MixerControlChangeCallback(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, PVOID Context)
00704 {
00705     UINT ControlCount = 0, Index;
00706     LPMIXERCONTROL Control = NULL;
00707 
00708     /* check if the line has controls */
00709     if (Line->cControls == 0)
00710     {
00711         /* no controls */
00712         return TRUE;
00713     }
00714 
00715     /* query controls */
00716     if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) == FALSE)
00717     {
00718         /* failed to query for controls */
00719         return FALSE;
00720     }
00721 
00722     /* now go through all controls and compare control ids */
00723     for(Index = 0; Index < ControlCount; Index++)
00724     {
00725         if (Control[Index].dwControlID == PtrToUlong(Context))
00726         {
00727             if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_SWITCH)
00728             {
00729                 MIXERCONTROLDETAILS_BOOLEAN Details;
00730 
00731                 /* get volume control details */
00732                 if (SndMixerGetVolumeControlDetails(Preferences.MixerWindow->Mixer, Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&Details) != -1)
00733                 {
00734                     /* update dialog control */
00735                     UpdateDialogLineSwitchControl(&Preferences, Line, Details.fValue);
00736                 }
00737             }
00738             else if ((Control[Index].dwControlType & MIXERCONTROL_CT_CLASS_MASK) == MIXERCONTROL_CT_CLASS_FADER)
00739             {
00740                 MIXERCONTROLDETAILS_UNSIGNED Details;
00741 
00742                 /* get volume control details */
00743                 if (SndMixerGetVolumeControlDetails(Preferences.MixerWindow->Mixer, Control[Index].dwControlID, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)&Details) != -1)
00744                 {
00745                     /* update dialog control */
00746                     DWORD Position;
00747                     DWORD Step = 0x10000 / 5;
00748 
00749                     /* FIXME: give me granularity */
00750                     Position = 5 - (Details.dwValue / Step);
00751 
00752                     /* update volume control slider */
00753                     UpdateDialogLineSliderControl(&Preferences, Line, Control[Index].dwControlID, IDC_LINE_SLIDER_VERT, Position);
00754                 }
00755             }
00756             break;
00757         }
00758     }
00759 
00760     /* free controls */
00761     HeapFree(GetProcessHeap(), 0, Control);
00762 
00763 
00764     /* done */
00765     return TRUE;
00766 }
00767 
00768 
00769 static LRESULT CALLBACK
00770 MainWindowProc(HWND hwnd,
00771                UINT uMsg,
00772                WPARAM wParam,
00773                LPARAM lParam)
00774 {
00775     PMIXER_WINDOW MixerWindow;
00776     DWORD CtrlID, LineOffset;
00777     LRESULT Result = 0;
00778     SET_VOLUME_CONTEXT Context;
00779 
00780     switch (uMsg)
00781     {
00782         case WM_COMMAND:
00783         {
00784             MixerWindow = GetWindowData(hwnd,
00785                                         MIXER_WINDOW);
00786 
00787             switch (LOWORD(wParam))
00788             {
00789                 case IDC_PROPERTIES:
00790                 {
00791                     PREFERENCES_CONTEXT Pref;
00792 
00793                     Pref.MixerWindow = MixerWindow;
00794                     Pref.Mixer = NULL;
00795                     Pref.SelectedLine = Preferences.SelectedLine;
00796 
00797                     if (DialogBoxParam(hAppInstance,
00798                                        MAKEINTRESOURCE(IDD_PREFERENCES),
00799                                        hwnd,
00800                                        DlgPreferencesProc,
00801                                        (LPARAM)&Pref) == IDOK)
00802                     {
00803                         /* update window */
00804                         TCHAR szProduct[MAXPNAMELEN];
00805 
00806                         /* get mixer product name */
00807                         if (SndMixerGetProductName(MixerWindow->Mixer,
00808                                                    szProduct,
00809                                                    sizeof(szProduct) / sizeof(szProduct[0])) == -1)
00810                         {
00811                             /* failed to get name */
00812                             szProduct[0] = L'\0';
00813                         }
00814                         else
00815                         {
00816                             /* copy product */
00817                             wcscpy(Preferences.DeviceName, szProduct);
00818                         }
00819 
00820                         /* destroy old status bar */
00821                         DestroyWindow(MixerWindow->hStatusBar);
00822 
00823                         /* update details */
00824                         Preferences.SelectedLine = Pref.SelectedLine;
00825 
00826                         /* destroy old mixer */
00827                         SndMixerDestroy(Preferences.MixerWindow->Mixer);
00828 
00829                         /* use new selected mixer */
00830                         Preferences.MixerWindow->Mixer = Pref.Mixer;
00831 
00832                         /* rebuild dialog controls */
00833                         RebuildMixerWindowControls(&Preferences);
00834 
00835                         /* create status window */
00836                         MixerWindow->hStatusBar = CreateStatusWindow(WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
00837                                                                      NULL,
00838                                                                      hwnd,
00839                                                                      0);
00840 
00841                         /* set status bar */
00842                         if (MixerWindow->hStatusBar)
00843                         {
00844                             SendMessage(MixerWindow->hStatusBar,
00845                                 WM_SETTEXT,
00846                                 0,
00847                                 (LPARAM)szProduct);
00848                         }
00849                     }
00850                     break;
00851                 }
00852 
00853                 case IDC_EXIT:
00854                 {
00855                     PostQuitMessage(0);
00856                     break;
00857                 }
00858 
00859                 case IDC_ABOUT:
00860                 {
00861                     HICON hAppIcon = (HICON)GetClassLongPtrW(hwnd,
00862                                                              GCLP_HICON);
00863                     ShellAbout(hwnd,
00864                                lpAppTitle,
00865                                NULL,
00866                                hAppIcon);
00867                     break;
00868                 }
00869 
00870                 default:
00871                 {
00872                     /* get button id */
00873                     CtrlID = LOWORD(wParam);
00874 
00875                     /* check if the message is from the line switch */
00876                     if (HIWORD(wParam) == BN_CLICKED && (CtrlID % IDC_LINE_SWITCH == 0))
00877                     {
00878                          /* compute line offset */
00879                          LineOffset = CtrlID / IDC_LINE_SWITCH;
00880 
00881                         /* compute window id of line name static control */
00882                         CtrlID = LineOffset * IDC_LINE_NAME;
00883 
00884                        /* get line name */
00885                        if (GetDlgItemTextW(hwnd, CtrlID, Context.LineName, MIXER_LONG_NAME_CHARS) != 0)
00886                        {
00887                            /* setup context */
00888                            Context.SliderPos = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0);
00889                            Context.bVertical = FALSE;
00890                            Context.bSwitch = TRUE;
00891 
00892                            /* set volume */
00893                            SndMixerEnumConnections(Preferences.MixerWindow->Mixer, Preferences.SelectedLine, SetVolumeCallback, (LPVOID)&Context);
00894                        }
00895                     }
00896                 }
00897 
00898             }
00899             break;
00900         }
00901 
00902         case MM_MIXM_LINE_CHANGE:
00903         {
00904             DPRINT("MM_MIXM_LINE_CHANGE\n");
00905             break;
00906         }
00907 
00908         case MM_MIXM_CONTROL_CHANGE:
00909         {
00910             DPRINT("MM_MIXM_CONTROL_CHANGE\n");
00911 
00912             /* get mixer window */
00913             MixerWindow = GetWindowData(hwnd,
00914                                         MIXER_WINDOW);
00915 
00916             /* sanity checks */
00917             assert(MixerWindow);
00918             assert(MixerWindow->Mixer->hmx == (HMIXER)wParam);
00919 
00920             SndMixerEnumConnections(MixerWindow->Mixer, Preferences.SelectedLine, MixerControlChangeCallback, (PVOID)lParam);
00921             break;
00922         }
00923 
00924         case WM_VSCROLL:
00925         {
00926             if (LOWORD(wParam) == TB_THUMBTRACK)
00927             {
00928                 /* get dialog item ctrl */
00929                 CtrlID = GetDlgCtrlID((HWND)lParam);
00930 
00931                 /* get line index */
00932                 LineOffset = CtrlID / IDC_LINE_SLIDER_VERT;
00933 
00934                 /* compute window id of line name static control */
00935                 CtrlID = LineOffset * IDC_LINE_NAME;
00936 
00937                 /* get line name */
00938                 if (GetDlgItemTextW(hwnd, CtrlID, Context.LineName, MIXER_LONG_NAME_CHARS) != 0)
00939                 {
00940                     /* setup context */
00941                     Context.SliderPos = HIWORD(wParam);
00942                     Context.bVertical = TRUE;
00943                     Context.bSwitch = FALSE;
00944 
00945                     /* set volume */
00946                     SndMixerEnumConnections(Preferences.MixerWindow->Mixer, Preferences.SelectedLine, SetVolumeCallback, (LPVOID)&Context);
00947                 }
00948             }
00949 
00950             break;
00951         }
00952 
00953 
00954         case WM_CREATE:
00955         {
00956             MixerWindow = ((LPCREATESTRUCT)lParam)->lpCreateParams;
00957             SetWindowLongPtr(hwnd,
00958                              GWL_USERDATA,
00959                              (LONG_PTR)MixerWindow);
00960             MixerWindow->hWnd = hwnd;
00961             MixerWindow->Mixer = SndMixerCreate(MixerWindow->hWnd);
00962             if (MixerWindow->Mixer != NULL)
00963             {
00964                 TCHAR szProduct[MAXPNAMELEN];
00965 
00966                 /* get mixer product name */
00967                 if (SndMixerGetProductName(MixerWindow->Mixer,
00968                                            szProduct,
00969                                            sizeof(szProduct) / sizeof(szProduct[0])) == -1)
00970                 {
00971                     /* failed to get name */
00972                     szProduct[0] = L'\0';
00973                 }
00974 
00975 
00976                 /* initialize perferences */
00977                 ZeroMemory(&Preferences, sizeof(Preferences));
00978 
00979                 /* store mixer */
00980                 Preferences.Mixer = MixerWindow->Mixer;
00981 
00982                 /* store mixer window */
00983                 Preferences.MixerWindow = MixerWindow;
00984 
00985                 /* first destination line id */
00986                 Preferences.SelectedLine = 0xFFFF0000;
00987 
00988                 /* copy product */
00989                 wcscpy(Preferences.DeviceName, szProduct);
00990 
00991                 if (!RebuildMixerWindowControls(&Preferences))
00992                 {
00993                     DPRINT("Rebuilding mixer window controls failed!\n");
00994                     SndMixerDestroy(MixerWindow->Mixer);
00995                     MixerWindow->Mixer = NULL;
00996                     Result = -1;
00997                 }
00998 
00999                 /* create status window */
01000                 MixerWindow->hStatusBar = CreateStatusWindow(WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
01001                                                              NULL,
01002                                                              hwnd,
01003                                                              0);
01004                 if (MixerWindow->hStatusBar)
01005                 {
01006                     SendMessage(MixerWindow->hStatusBar,
01007                                 WM_SETTEXT,
01008                                 0,
01009                                 (LPARAM)szProduct);
01010                 }
01011             }
01012             break;
01013         }
01014 
01015         case WM_DESTROY:
01016         {
01017             MixerWindow = GetWindowData(hwnd,
01018                                         MIXER_WINDOW);
01019             if (MixerWindow->Mixer != NULL)
01020             {
01021                 SndMixerDestroy(MixerWindow->Mixer);
01022             }
01023             break;
01024         }
01025 
01026         case WM_CLOSE:
01027         {
01028             PostQuitMessage(0);
01029             break;
01030         }
01031 
01032         default:
01033         {
01034             Result = DefWindowProc(hwnd,
01035                                    uMsg,
01036                                    wParam,
01037                                    lParam);
01038             break;
01039         }
01040     }
01041 
01042     return Result;
01043 }
01044 
01045 static BOOL
01046 RegisterApplicationClasses(VOID)
01047 {
01048     WNDCLASSEX wc;
01049 
01050     wc.cbSize = sizeof(WNDCLASSEX);
01051     wc.style = CS_HREDRAW | CS_VREDRAW;
01052     wc.lpfnWndProc = MainWindowProc;
01053     wc.cbClsExtra = 0;
01054     wc.cbWndExtra = sizeof(PMIXER_WINDOW);
01055     wc.hInstance = hAppInstance;
01056     wc.hIcon = LoadIcon(hAppInstance,
01057                         MAKEINTRESOURCE(IDI_MAINAPP));
01058     wc.hCursor = LoadCursor(NULL,
01059                             IDC_ARROW);
01060     wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
01061     wc.lpszMenuName = NULL;
01062     wc.lpszClassName = SZ_APP_CLASS;
01063     wc.hIconSm = NULL;
01064     MainWindowClass = RegisterClassEx(&wc);
01065 
01066     return MainWindowClass != 0;
01067 }
01068 
01069 static VOID
01070 UnregisterApplicationClasses(VOID)
01071 {
01072     UnregisterClass(SZ_APP_CLASS,
01073                     hAppInstance);
01074 }
01075 
01076 static HWND
01077 CreateApplicationWindow(VOID)
01078 {
01079     HWND hWnd;
01080 
01081     PMIXER_WINDOW MixerWindow = HeapAlloc(hAppHeap,
01082                                           HEAP_ZERO_MEMORY,
01083                                           sizeof(MIXER_WINDOW));
01084     if (MixerWindow == NULL)
01085     {
01086         return NULL;
01087     }
01088 
01089     if (mixerGetNumDevs() > 0)
01090     {
01091         hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT,
01092                               SZ_APP_CLASS,
01093                               lpAppTitle,
01094                               WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, 
01095                               0, 0, 300, 315,
01096                               NULL,
01097                               LoadMenu(hAppInstance,
01098                                        MAKEINTRESOURCE(IDM_MAINMENU)),
01099                               hAppInstance,
01100                               MixerWindow);
01101     }
01102     else
01103     {
01104         LPTSTR lpErrMessage;
01105 
01106         /*
01107          * no mixer devices are available!
01108          */
01109 
01110         hWnd = NULL;
01111         if (AllocAndLoadString(&lpErrMessage,
01112                                hAppInstance,
01113                                IDS_NOMIXERDEVICES))
01114         {
01115             MessageBox(NULL,
01116                        lpErrMessage,
01117                        lpAppTitle,
01118                        MB_ICONINFORMATION);
01119             LocalFree(lpErrMessage);
01120         }
01121     }
01122 
01123     if (hWnd == NULL)
01124     {
01125         HeapFree(hAppHeap,
01126                  0,
01127                  MixerWindow);
01128     }
01129 
01130     return hWnd;
01131 }
01132 
01133 int WINAPI
01134 _tWinMain(HINSTANCE hInstance,
01135           HINSTANCE hPrevInstance,
01136           LPTSTR lpszCmdLine,
01137           int nCmdShow)
01138 {
01139     MSG Msg;
01140     int Ret = 1;
01141     INITCOMMONCONTROLSEX Controls;
01142 
01143     UNREFERENCED_PARAMETER(hPrevInstance);
01144     UNREFERENCED_PARAMETER(lpszCmdLine);
01145     UNREFERENCED_PARAMETER(nCmdShow);
01146 
01147     hAppInstance = hInstance;
01148     hAppHeap = GetProcessHeap();
01149 
01150     if (InitAppConfig())
01151     {
01152         /* load the application title */
01153         if (!AllocAndLoadString(&lpAppTitle,
01154                                 hAppInstance,
01155                                 IDS_SNDVOL32))
01156         {
01157             lpAppTitle = NULL;
01158         }
01159 
01160         Controls.dwSize = sizeof(INITCOMMONCONTROLSEX);
01161         Controls.dwICC = ICC_BAR_CLASSES | ICC_STANDARD_CLASSES;
01162 
01163         InitCommonControlsEx(&Controls);
01164 
01165         if (RegisterApplicationClasses())
01166         {
01167             hMainWnd = CreateApplicationWindow();
01168             if (hMainWnd != NULL)
01169             {
01170                 BOOL bRet;
01171                 while ((bRet =GetMessage(&Msg,
01172                                          NULL,
01173                                          0,
01174                                          0)) != 0)
01175                 {
01176                     if (bRet != -1)
01177                     {
01178                         TranslateMessage(&Msg);
01179                         DispatchMessage(&Msg);
01180                     }
01181                 }
01182 
01183                 DestroyWindow(hMainWnd);
01184                 Ret = 0;
01185             }
01186             else
01187             {
01188                 DPRINT("Failed to create application window (LastError: %d)!\n", GetLastError());
01189             }
01190 
01191             UnregisterApplicationClasses();
01192         }
01193         else
01194         {
01195             DPRINT("Failed to register application classes (LastError: %d)!\n", GetLastError());
01196         }
01197 
01198         if (lpAppTitle != NULL)
01199         {
01200             LocalFree(lpAppTitle);
01201         }
01202 
01203         CloseAppConfig();
01204     }
01205     else
01206     {
01207         DPRINT("Unable to open the Volume Control registry key!\n");
01208     }
01209 
01210     return Ret;
01211 }
01212 

Generated on Fri May 25 2012 04:15:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.