From 15c755e5f9eedd3ea60320432d24160b00866a48 Mon Sep 17 00:00:00 2001 From: Thamatip Chitpong Date: Thu, 13 Apr 2023 03:00:37 +0700 Subject: [PATCH] [MMSYS] Improve sound test button (#4879) - Make sound test button able to stop the sound (like WinXP's mmsys.cpl) - Change stop icon - Add documentation for GetSoundDuration --- dll/cpl/mmsys/resources/stop.ico | Bin 4286 -> 326 bytes dll/cpl/mmsys/sounds.c | 165 ++++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 5 deletions(-) diff --git a/dll/cpl/mmsys/resources/stop.ico b/dll/cpl/mmsys/resources/stop.ico index a0b001ad1f36cf6e758d71d2b6b83c5bb3a67d0e..eca39a1ea0cfb95029b58d1f46e3506edb00bb1e 100644 GIT binary patch literal 326 xcmZQzU<5)11tu_Uz{tQL#=yX!0mKSG>;S|d`N0nU6AKRT|Nl=cCe}=#Isg-vbCUo7 literal 4286 zcmeH~$%+$E6o#*RCDLj;ps}66Rh~ie3L3gaHxb+@xDbg85wj4%g$ROR@C78hEVIoc zD6Of^SgFcbN!rR>nU3ebMKwWf?DlRHs=^;aCI9*AocrGk5#k8HHZ}y_#i!#!tP3Ho zv-p;{!NPt2@+aU=;QyNd5glc%9aOe$udT|mtYa!&o2Gf<{l^dVw}M}VuW8!JH}Brk zcrsy)X*7mLG#o)g8VsQU^#`tcgFf~8eX{#Kf)9QbekPMS_44&Anm7)9w{7a~?oy}Q zC9Bh>R@!;8)?N)9LkR@#i$*{=sf{I(zH}v+KWM zSE{C*3w)_m>a+?!nM|H}{PYQpc=qVk(94w9OOz`YX~5Zl4}KMXJRUz6y?>8}oHMgtmHicUT{6Jg zDHWu&VxF=EC`aG&J2Ic}!LP!P#bW2T?%tNU_tx86g9_&i^G45FF-O}ujlN{J>2vn0 z{5^c|tMH@I=!Kh`w`4tUy^(QG2G2x_p9Q&xu>RPm@WHRbk3=Ft)WP0IZDeduoB=ln z$by>(H-8o0uM^3KUxgnIhcAMUdf=7}R(6@DNPxB@=v&1N%l_#8fnmdmB&!>__;?^WhhZ(E%L7m diff --git a/dll/cpl/mmsys/sounds.c b/dll/cpl/mmsys/sounds.c index 5285599908c..cec3e34e273 100644 --- a/dll/cpl/mmsys/sounds.c +++ b/dll/cpl/mmsys/sounds.c @@ -16,6 +16,8 @@ #include +#define ID_SOUND_TEST_TIMER 1 + typedef struct _LABEL_MAP { PWCHAR szName; @@ -57,6 +59,8 @@ typedef struct _GLOBAL_DATA PLABEL_MAP pLabelMap; PAPP_MAP pAppMap; UINT NumWavOut; + HICON hPlayIcon; + HICON hStopIcon; } GLOBAL_DATA, *PGLOBAL_DATA; @@ -1140,6 +1144,99 @@ InitImageList(UINT StartResource, } +/** + * @brief + * Get the duration of a waveform audio file. + * + * @param[in] pFileName + * The file name or full path of the file. + * + * @return + * The duration of the sound, in milliseconds. + * Returns 0 in case of failure. + **/ +static +DWORD +GetSoundDuration(LPCWSTR pFileName) +{ + MCI_OPEN_PARMSW openParms; + MCI_GENERIC_PARMS closeParms; + MCI_SET_PARMS setParms; + MCI_STATUS_PARMS statusParms; + MCIERROR mciError; + + ZeroMemory(&openParms, sizeof(openParms)); + openParms.lpstrDeviceType = L"waveaudio"; + openParms.lpstrElementName = pFileName; + + mciError = mciSendCommandW(0, + MCI_OPEN, + MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_WAIT, + (DWORD_PTR)&openParms); + if (mciError != 0) + return 0; + + ZeroMemory(&setParms, sizeof(setParms)); + setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS; + + mciError = mciSendCommandW(openParms.wDeviceID, + MCI_SET, + MCI_SET_TIME_FORMAT | MCI_WAIT, + (DWORD_PTR)&setParms); + if (mciError == 0) + { + ZeroMemory(&statusParms, sizeof(statusParms)); + statusParms.dwItem = MCI_STATUS_LENGTH; + + mciError = mciSendCommandW(openParms.wDeviceID, + MCI_STATUS, + MCI_STATUS_ITEM | MCI_WAIT, + (DWORD_PTR)&statusParms); + } + + closeParms.dwCallback = 0; + mciSendCommandW(openParms.wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD_PTR)&closeParms); + + if (mciError != 0) + return 0; + + return statusParms.dwReturn; +} + +static +BOOL +StartSoundTest(HWND hwndDlg, LPCWSTR pszSound) +{ + DWORD dwDuration; + + dwDuration = GetSoundDuration(pszSound); + if (dwDuration == 0) + return FALSE; + + if (PlaySoundW(pszSound, NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT)) + { + SetTimer(hwndDlg, ID_SOUND_TEST_TIMER, dwDuration, NULL); + return TRUE; + } + + return FALSE; +} + +static +BOOL +StopSoundTest(HWND hwndDlg) +{ + /* Check if the sound is playing */ + if (KillTimer(hwndDlg, ID_SOUND_TEST_TIMER)) + { + /* Stop the sound */ + PlaySoundW(NULL, NULL, SND_ASYNC); + return TRUE; + } + + return FALSE; +} + /* Sounds property page dialog callback */ INT_PTR CALLBACK @@ -1167,9 +1264,20 @@ SoundsDlgProc(HWND hwndDlg, pGlobalData->NumWavOut = waveOutGetNumDevs(); - SendMessageW(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), - BM_SETIMAGE, (WPARAM)IMAGE_ICON, - (LPARAM)(HANDLE)LoadIconW(hApplet, MAKEINTRESOURCEW(IDI_PLAY_ICON))); + pGlobalData->hPlayIcon = LoadImageW(hApplet, + MAKEINTRESOURCEW(IDI_PLAY_ICON), + IMAGE_ICON, + 32, + 32, + LR_DEFAULTCOLOR); + pGlobalData->hStopIcon = LoadImageW(hApplet, + MAKEINTRESOURCEW(IDI_STOP_ICON), + IMAGE_ICON, + 32, + 32, + LR_DEFAULTCOLOR); + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hPlayIcon); pGlobalData->hSoundsImageList = InitImageList(IDI_SOUND_SECTION, IDI_SOUND_ASSIGNED, @@ -1236,6 +1344,14 @@ SoundsDlgProc(HWND hwndDlg, case IDC_PLAY_SOUND: { LRESULT lIndex; + + if (StopSoundTest(hwndDlg)) + { + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hPlayIcon); + break; + } + lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST)); if (lIndex == CB_ERR) { @@ -1245,7 +1361,11 @@ SoundsDlgProc(HWND hwndDlg, lIndex = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex); if (lIndex != CB_ERR) { - PlaySoundW((PWCHAR)lIndex, NULL, SND_FILENAME); + if (StartSoundTest(hwndDlg, (LPWSTR)lIndex)) + { + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hStopIcon); + } } break; } @@ -1346,12 +1466,20 @@ SoundsDlgProc(HWND hwndDlg, } case WM_DESTROY: { + StopSoundTest(hwndDlg); FreeSoundFiles(hwndDlg); FreeSoundProfiles(hwndDlg); FreeAppMap(pGlobalData); FreeLabelMap(pGlobalData); if (pGlobalData->hSoundsImageList) ImageList_Destroy(pGlobalData->hSoundsImageList); + + if (pGlobalData->hStopIcon) + DestroyIcon(pGlobalData->hStopIcon); + + if (pGlobalData->hPlayIcon) + DestroyIcon(pGlobalData->hPlayIcon); + HeapFree(GetProcessHeap(), 0, pGlobalData); break; } @@ -1369,11 +1497,27 @@ SoundsDlgProc(HWND hwndDlg, ApplyChanges(hwndDlg); break; } + case PSN_KILLACTIVE: + { + if (StopSoundTest(hwndDlg)) + { + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hPlayIcon); + } + + break; + } case TVN_SELCHANGED: { LPNMTREEVIEWW nm = (LPNMTREEVIEWW)lParam; LRESULT lCount, lIndex, lResult; + if (StopSoundTest(hwndDlg)) + { + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hPlayIcon); + } + pLabelContext = (PLABEL_CONTEXT)nm->itemNew.lParam; if (pLabelContext == NULL) { @@ -1431,8 +1575,19 @@ SoundsDlgProc(HWND hwndDlg, break; } } + break; + } + case WM_TIMER: + { + if (wParam == ID_SOUND_TEST_TIMER) + { + KillTimer(hwndDlg, ID_SOUND_TEST_TIMER); + SendDlgItemMessageW(hwndDlg, IDC_PLAY_SOUND, BM_SETIMAGE, + IMAGE_ICON, (LPARAM)pGlobalData->hPlayIcon); + } + + break; } - break; } return FALSE;