//==========================================================================; // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (c) 1992 - 1994 Microsoft Corporation. All Rights Reserved. //--------------------------------------------------------------------------; // // aaprops.c // // Description: // // // //==========================================================================; #include #include #include #include #include #include #include "muldiv32.h" #include "appport.h" #include "acmapp.h" #include "debug.h" //==========================================================================; // // // // //==========================================================================; //--------------------------------------------------------------------------; // // BOOL AcmAppGetErrorString // // Description: // // // Arguments: // MMRESULT mmr: // // PTSTR psz: // // Return (BOOL): // // //--------------------------------------------------------------------------; BOOL FNGLOBAL AcmAppGetErrorString ( MMRESULT mmr, LPTSTR pszError ) { PTSTR psz; switch (mmr) { case MMSYSERR_NOERROR: psz = TEXT("MMSYSERR_NOERROR"); break; case MMSYSERR_ERROR: psz = TEXT("MMSYSERR_ERROR"); break; case MMSYSERR_BADDEVICEID: psz = TEXT("MMSYSERR_BADDEVICEID"); break; case MMSYSERR_NOTENABLED: psz = TEXT("MMSYSERR_NOTENABLED"); break; case MMSYSERR_ALLOCATED: psz = TEXT("MMSYSERR_ALLOCATED"); break; case MMSYSERR_INVALHANDLE: psz = TEXT("MMSYSERR_INVALHANDLE"); break; case MMSYSERR_NODRIVER: psz = TEXT("MMSYSERR_NODRIVER"); break; case MMSYSERR_NOMEM: psz = TEXT("MMSYSERR_NOMEM"); break; case MMSYSERR_NOTSUPPORTED: psz = TEXT("MMSYSERR_NOTSUPPORTED"); break; case MMSYSERR_BADERRNUM: psz = TEXT("MMSYSERR_BADERRNUM"); break; case MMSYSERR_INVALFLAG: psz = TEXT("MMSYSERR_INVALFLAG"); break; case MMSYSERR_INVALPARAM: psz = TEXT("MMSYSERR_INVALPARAM"); break; case WAVERR_BADFORMAT: psz = TEXT("WAVERR_BADFORMAT"); break; case WAVERR_STILLPLAYING: psz = TEXT("WAVERR_STILLPLAYING"); break; case WAVERR_UNPREPARED: psz = TEXT("WAVERR_UNPREPARED"); break; case WAVERR_SYNC: psz = TEXT("WAVERR_SYNC"); break; case ACMERR_NOTPOSSIBLE: psz = TEXT("ACMERR_NOTPOSSIBLE"); break; case ACMERR_BUSY: psz = TEXT("ACMERR_BUSY"); break; case ACMERR_UNPREPARED: psz = TEXT("ACMERR_UNPREPARED"); break; case ACMERR_CANCELED: psz = TEXT("ACMERR_CANCELED"); break; default: lstrcpy(pszError, TEXT("(unknown)")); return (FALSE); } lstrcpy(pszError, psz); return (TRUE); } // AcmAppGetErrorString() //--------------------------------------------------------------------------; // // BOOL AcmAppGetFormatDescription // // Description: // // // Arguments: // LPWAVEFORMATEX pwfx: // // LPSTR pszFormatTag: // // LPSTR pszFormat: // // Return (BOOL): // // //--------------------------------------------------------------------------; TCHAR gszIntl[] = TEXT("Intl"); TCHAR gszIntlList[] = TEXT("sList"); TCHAR gszIntlDecimal[] = TEXT("sDecimal"); TCHAR gchIntlList = ','; TCHAR gchIntlDecimal = '.'; BOOL FNGLOBAL AcmAppGetFormatDescription ( LPWAVEFORMATEX pwfx, LPTSTR pszFormatTag, LPTSTR pszFormat ) { MMRESULT mmr; BOOL f; f = TRUE; // // get the name for the format tag of the specified format // if (NULL != pszFormatTag) { ACMFORMATTAGDETAILS aftd; // // initialize all unused members of the ACMFORMATTAGDETAILS // structure to zero // memset(&aftd, 0, sizeof(aftd)); // // fill in the required members of the ACMFORMATTAGDETAILS // structure for the ACM_FORMATTAGDETAILSF_FORMATTAG query // aftd.cbStruct = sizeof(aftd); aftd.dwFormatTag = pwfx->wFormatTag; // // ask the ACM to find the first available driver that // supports the specified format tag // mmr = acmFormatTagDetails(NULL, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG); if (MMSYSERR_NOERROR == mmr) { // // copy the format tag name into the caller's buffer // lstrcpy(pszFormatTag, aftd.szFormatTag); } else { PTSTR psz; // // no ACM driver is available that supports the // specified format tag // f = FALSE; psz = NULL; // // the following stuff if proof that the world does NOT need // yet another ADPCM algorithm!! // switch (pwfx->wFormatTag) { case WAVE_FORMAT_UNKNOWN: psz = TEXT("** RESERVED INVALID TAG **"); break; case WAVE_FORMAT_PCM: psz = TEXT("PCM"); break; case WAVE_FORMAT_ADPCM: psz = TEXT("Microsoft ADPCM"); break; case 0x0003: psz = TEXT("MV's *UNREGISTERED* ADPCM"); break; case WAVE_FORMAT_IBM_CVSD: psz = TEXT("IBM CVSD"); break; case WAVE_FORMAT_ALAW: psz = TEXT("A-Law"); break; case WAVE_FORMAT_MULAW: psz = TEXT("u-Law"); break; case WAVE_FORMAT_OKI_ADPCM: psz = TEXT("OKI ADPCM"); break; case WAVE_FORMAT_IMA_ADPCM: psz = TEXT("IMA/DVI ADPCM"); break; case WAVE_FORMAT_DIGISTD: psz = TEXT("DIGI STD"); break; case WAVE_FORMAT_DIGIFIX: psz = TEXT("DIGI FIX"); break; case WAVE_FORMAT_YAMAHA_ADPCM: psz = TEXT("Yamaha ADPCM"); break; case WAVE_FORMAT_SONARC: psz = TEXT("Sonarc"); break; case WAVE_FORMAT_DSPGROUP_TRUESPEECH: psz = TEXT("DSP Group TrueSpeech"); break; case WAVE_FORMAT_ECHOSC1: psz = TEXT("Echo SC1"); break; case WAVE_FORMAT_AUDIOFILE_AF36: psz = TEXT("Audiofile AF36"); break; case WAVE_FORMAT_CREATIVE_ADPCM: psz = TEXT("Creative Labs ADPCM"); break; case WAVE_FORMAT_APTX: psz = TEXT("APTX"); break; case WAVE_FORMAT_AUDIOFILE_AF10: psz = TEXT("Audiofile AF10"); break; case WAVE_FORMAT_DOLBY_AC2: psz = TEXT("Dolby AC2"); break; case WAVE_FORMAT_MEDIASPACE_ADPCM: psz = TEXT("Media Space ADPCM"); break; case WAVE_FORMAT_SIERRA_ADPCM: psz = TEXT("Sierra ADPCM"); break; case WAVE_FORMAT_G723_ADPCM: psz = TEXT("CCITT G.723 ADPCM"); break; case WAVE_FORMAT_GSM610: psz = TEXT("GSM 6.10"); break; case WAVE_FORMAT_G721_ADPCM: psz = TEXT("CCITT G.721 ADPCM"); break; case WAVE_FORMAT_DEVELOPMENT: psz = TEXT("** RESERVED DEVELOPMENT ONLY TAG **"); break; default: wsprintf(pszFormatTag, TEXT("[%u] (unknown)"), pwfx->wFormatTag); break; } if (NULL != psz) { lstrcpy(pszFormatTag, psz); } } } // // get the description of the attributes for the specified // format // if (NULL != pszFormat) { ACMFORMATDETAILS afd; // // initialize all unused members of the ACMFORMATDETAILS // structure to zero // memset(&afd, 0, sizeof(afd)); // // fill in the required members of the ACMFORMATDETAILS // structure for the ACM_FORMATDETAILSF_FORMAT query // afd.cbStruct = sizeof(afd); afd.dwFormatTag = pwfx->wFormatTag; afd.pwfx = pwfx; // // the cbwfx member must be initialized to the total size // in bytes needed for the specified format. for a PCM // format, the cbSize member of the WAVEFORMATEX structure // is not valid. // if (WAVE_FORMAT_PCM == pwfx->wFormatTag) { afd.cbwfx = sizeof(PCMWAVEFORMAT); } else { afd.cbwfx = sizeof(WAVEFORMATEX) + pwfx->cbSize; } // // ask the ACM to find the first available driver that // supports the specified format // mmr = acmFormatDetails(NULL, &afd, ACM_FORMATDETAILSF_FORMAT); if (MMSYSERR_NOERROR == mmr) { // // copy the format attributes description into the caller's // buffer // lstrcpy(pszFormat, afd.szFormat); } else { TCHAR ach[2]; TCHAR szChannels[24]; UINT cBits; // // no ACM driver is available that supports the // specified format // f = FALSE; // // // ach[0] = gchIntlList; ach[1] = '\0'; GetProfileString(gszIntl, gszIntlList, ach, ach, sizeof(ach)); gchIntlList = ach[0]; ach[0] = gchIntlDecimal; ach[1] = '\0'; GetProfileString(gszIntl, gszIntlDecimal, ach, ach, sizeof(ach)); gchIntlDecimal = ach[0]; // // compute the bit depth--this _should_ be the same as // wBitsPerSample, but isn't always... // cBits = (UINT)(pwfx->nAvgBytesPerSec * 8 / pwfx->nSamplesPerSec / pwfx->nChannels); if ((1 == pwfx->nChannels) || (2 == pwfx->nChannels)) { if (1 == pwfx->nChannels) lstrcpy(szChannels, TEXT("Mono")); else lstrcpy(szChannels, TEXT("Stereo")); wsprintf(pszFormat, TEXT("%lu%c%.03u kHz%c %u Bit%c %s"), pwfx->nSamplesPerSec / 1000, gchIntlDecimal, (UINT)(pwfx->nSamplesPerSec % 1000), gchIntlList, cBits, gchIntlList, (LPTSTR)szChannels); } else { wsprintf(pszFormat, TEXT("%lu%c%.03u kHz%c %u Bit%c %u Channels"), pwfx->nSamplesPerSec / 1000, gchIntlDecimal, (UINT)(pwfx->nSamplesPerSec % 1000), gchIntlList, cBits, gchIntlList, pwfx->nChannels); } } } // // // return (f); } // AcmAppGetFormatDescription() //--------------------------------------------------------------------------; // // BOOL AcmAppGetFilterDescription // // Description: // // // Arguments: // LPWAVEFILTER pwfltr: // // LPSTR pszFilterTag: // // LPSTR pszFilter: // // Return (BOOL): // // //--------------------------------------------------------------------------; BOOL FNGLOBAL AcmAppGetFilterDescription ( LPWAVEFILTER pwfltr, LPTSTR pszFilterTag, LPTSTR pszFilter ) { MMRESULT mmr; BOOL f; f = TRUE; // // get the name for the filter tag of the specified filter // if (NULL != pszFilterTag) { ACMFILTERTAGDETAILS aftd; // // initialize all unused members of the ACMFILTERTAGDETAILS // structure to zero // memset(&aftd, 0, sizeof(aftd)); // // fill in the required members of the ACMFILTERTAGDETAILS // structure for the ACM_FILTERTAGDETAILSF_FILTERTAG query // aftd.cbStruct = sizeof(aftd); aftd.dwFilterTag = pwfltr->dwFilterTag; // // ask the ACM to find the first available driver that // supports the specified filter tag // mmr = acmFilterTagDetails(NULL, &aftd, ACM_FILTERTAGDETAILSF_FILTERTAG); if (MMSYSERR_NOERROR == mmr) { // // copy the filter tag name into the caller's buffer // lstrcpy(pszFilterTag, aftd.szFilterTag); } else { PTSTR psz; psz = NULL; f = FALSE; // // no ACM driver is available that supports the // specified filter tag // switch (pwfltr->dwFilterTag) { case WAVE_FILTER_UNKNOWN: psz = TEXT("** RESERVED INVALID TAG **"); break; case WAVE_FILTER_VOLUME: psz = TEXT("Microsoft Volume Filter"); break; case WAVE_FILTER_ECHO: psz = TEXT("Microsoft Echo Filter"); break; case WAVE_FILTER_DEVELOPMENT: psz = TEXT("** RESERVED DEVELOPMENT ONLY TAG **"); break; default: wsprintf(pszFilterTag, TEXT("[%lu] (unknown)"),pwfltr->dwFilterTag); break; } if (NULL != psz) { lstrcpy(pszFilterTag, psz); } } } // // get the description of the attributes for the specified // filter // if (NULL != pszFilter) { ACMFILTERDETAILS afd; // // initialize all unused members of the ACMFILTERDETAILS // structure to zero // memset(&afd, 0, sizeof(afd)); // // fill in the required members of the ACMFILTERDETAILS // structure for the ACM_FILTERDETAILSF_FILTER query // afd.cbStruct = sizeof(afd); afd.dwFilterTag = pwfltr->dwFilterTag; afd.pwfltr = pwfltr; afd.cbwfltr = pwfltr->cbStruct; // // ask the ACM to find the first available driver that // supports the specified filter // mmr = acmFilterDetails(NULL, &afd, ACM_FILTERDETAILSF_FILTER); if (MMSYSERR_NOERROR == mmr) { // // copy the filter attributes description into the caller's // buffer // lstrcpy(pszFilter, afd.szFilter); } else { // // no ACM driver is available that supports the // specified filter // f = FALSE; wsprintf(pszFilter, TEXT("Unknown Filter %lu, %.08lXh"), pwfltr->dwFilterTag, pwfltr->fdwFilter); } } // // // return (f); } // AcmAppGetFilterDescription() //--------------------------------------------------------------------------; // // BOOL AcmAppDumpExtraHeaderData // // Description: // // // Arguments: // HWND hedit: // // LPWAVEFORMATEX pwfx: // // Return (BOOL): // // //--------------------------------------------------------------------------; BOOL FNLOCAL AcmAppDumpExtraHeaderData ( HWND hedit, LPWAVEFORMATEX pwfx ) { static TCHAR szDisplayTitle[] = TEXT("Offset Data Bytes"); if ((WAVE_FORMAT_PCM == pwfx->wFormatTag) || (0 == pwfx->cbSize)) return (TRUE); MEditPrintF(hedit, szDisplayTitle); MEditPrintF(hedit, TEXT("------ -----------------------------------------------")); // // !!! this is really horrible code !!! // { #define ACMAPP_DUMP_BYTES_PER_LINE 16 UINT u; UINT v; for (u = 0; u < pwfx->cbSize; u += ACMAPP_DUMP_BYTES_PER_LINE) { MEditPrintF(hedit, TEXT("~0x%.04X"), u); for (v = 0; v < ACMAPP_DUMP_BYTES_PER_LINE; v++) { if ((u + v) >= pwfx->cbSize) break; MEditPrintF(hedit, TEXT("~ %.02X"), ((LPBYTE)(pwfx + 1))[u + v]); } MEditPrintF(hedit, gszNull); } #undef ACMAPP_DUMP_BYTES_PER_LINE } return (TRUE); } // AcmAppDumpExtraHeaderData() //--------------------------------------------------------------------------; // // BOOL AcmAppDisplayFileProperties // // Description: // // // Arguments: // HWND hwnd: // // PACMAPPFILEDESC paafd: // // Return (BOOL): // //--------------------------------------------------------------------------; BOOL FNGLOBAL AcmAppDisplayFileProperties ( HWND hwnd, PACMAPPFILEDESC paafd ) { static TCHAR szInvalidWaveFile[] = TEXT("No File"); static TCHAR szDisplayTitle[] = TEXT("[Wave File Format Properties]\r\n"); MMRESULT mmr; TCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS]; TCHAR ach[APP_MAX_STRING_CHARS]; DWORD dw; LPWAVEFORMATEX pwfx; HWND hedit; HMENU hmenu; BOOL fCanPlayRecord; BOOL f; // // clear the display // AppHourGlass(TRUE); hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY); SetWindowRedraw(hedit, FALSE); MEditPrintF(hedit, NULL); // // // MEditPrintF(hedit, szDisplayTitle); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Title"), (LPTSTR)paafd->szFileTitle); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Full Path"), (LPTSTR)paafd->szFilePath); AppFormatBigNumber(ach, paafd->cbFileSize); MEditPrintF(hedit, TEXT("%25s: %s bytes"), (LPTSTR)TEXT("Total File Size"), (LPTSTR)ach); AppFormatDosDateTime(ach, paafd->uDosChangeDate, paafd->uDosChangeTime); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Last Change Date/Time"), (LPTSTR)ach); dw = paafd->fdwFileAttributes; MEditPrintF(hedit, TEXT("%25s: %c %c%c%c%c %c%c%c%c (%.08lXh)"), (LPTSTR)TEXT("Attributes"), (dw & FILE_ATTRIBUTE_TEMPORARY) ? 't' : '-', (dw & FILE_ATTRIBUTE_NORMAL) ? 'n' : '-', (dw & 0x00000040) ? '?' : '-', (dw & FILE_ATTRIBUTE_ARCHIVE) ? 'a' : '-', (dw & FILE_ATTRIBUTE_DIRECTORY) ? 'd' : '-', (dw & 0x00000008) ? '?' : '-', (dw & FILE_ATTRIBUTE_SYSTEM) ? 's' : '-', (dw & FILE_ATTRIBUTE_HIDDEN) ? 'h' : '-', (dw & FILE_ATTRIBUTE_READONLY) ? 'r' : '-', dw); pwfx = paafd->pwfx; if (NULL == pwfx) { fCanPlayRecord = FALSE; goto AA_Display_File_Properties_Exit; } // // // // f = AcmAppGetFormatDescription(pwfx, szFormatTag, ach); MEditPrintF(hedit, TEXT("\r\n%25s: %s%s"), (LPTSTR)TEXT("Format"), f ? (LPTSTR)gszNull : (LPTSTR)TEXT("*"), (LPTSTR)szFormatTag); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Attributes"), (LPTSTR)ach); AppFormatBigNumber(ach, paafd->dwDataBytes); MEditPrintF(hedit, TEXT("\r\n%25s: %s bytes"), (LPTSTR)TEXT("Data Size"), (LPTSTR)ach); AppFormatBigNumber(ach, paafd->dwDataBytes / pwfx->nAvgBytesPerSec); dw = paafd->dwDataBytes % pwfx->nAvgBytesPerSec; dw = (dw * 1000) / pwfx->nAvgBytesPerSec; MEditPrintF(hedit, TEXT("%25s: %s.%.03lu seconds"), (LPTSTR)TEXT("Play Time (avg bytes)"), (LPTSTR)ach, dw); AppFormatBigNumber(ach, paafd->dwDataSamples); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Total Samples"), (LPTSTR)ach); AppFormatBigNumber(ach, paafd->dwDataSamples / pwfx->nSamplesPerSec); dw = paafd->dwDataSamples % pwfx->nSamplesPerSec; dw = (dw * 1000) / pwfx->nSamplesPerSec; MEditPrintF(hedit, TEXT("%25s: %s.%.03lu seconds"), (LPTSTR)TEXT("Play Time (samples)"), (LPTSTR)ach, dw); // // // MEditPrintF(hedit, TEXT("\r\n%25s: %u"), (LPTSTR)TEXT("Format Tag"), pwfx->wFormatTag); MEditPrintF(hedit, TEXT("%25s: %u"), (LPTSTR)TEXT("Channels"), pwfx->nChannels); AppFormatBigNumber(ach, pwfx->nSamplesPerSec); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Samples Per Second"), (LPTSTR)ach); AppFormatBigNumber(ach, pwfx->nAvgBytesPerSec); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Avg Bytes Per Second"), (LPTSTR)ach); AppFormatBigNumber(ach, pwfx->nBlockAlign); MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Block Alignment"), (LPTSTR)ach); MEditPrintF(hedit, TEXT("%25s: %u"), (LPTSTR)TEXT("Bits Per Sample"), pwfx->wBitsPerSample); if (WAVE_FORMAT_PCM != pwfx->wFormatTag) { AppFormatBigNumber(ach, pwfx->cbSize); MEditPrintF(hedit, TEXT("%25s: %s bytes\r\n"), (LPTSTR)TEXT("Extra Format Information"), (LPTSTR)ach); AcmAppDumpExtraHeaderData(hedit, pwfx); } // // note that we do NOT set the 'WAVE_ALLOWSYNC' bit on queries because // the player/recorder dialog uses MCIWAVE--which cannot work with // SYNC devices. // mmr = waveOutOpen(NULL, guWaveOutId, #if (WINVER < 0x0400) (LPWAVEFORMAT)pwfx, #else pwfx, #endif 0L, 0L, WAVE_FORMAT_QUERY); fCanPlayRecord = (MMSYSERR_NOERROR == mmr); if (!fCanPlayRecord) { // // this situation can happen with the 'preferred' device settings // for the Sound Mapper. // mmr = waveInOpen(NULL, guWaveInId, #if (WINVER < 0x0400) (LPWAVEFORMAT)pwfx, #else pwfx, #endif 0L, 0L, WAVE_FORMAT_QUERY); fCanPlayRecord = (MMSYSERR_NOERROR == mmr); } AA_Display_File_Properties_Exit: hmenu = GetMenu(hwnd); EnableMenuItem(hmenu, IDM_PLAYRECORD, MF_BYCOMMAND | (fCanPlayRecord ? MF_ENABLED : MF_GRAYED)); DrawMenuBar(hwnd); Edit_SetSel(hedit, (WPARAM)0, (LPARAM)0); SetWindowRedraw(hedit, TRUE); AppHourGlass(FALSE); return (fCanPlayRecord); } // AcmAppDisplayFileProperties()