Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensndvol32.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
1.7.6.1
|