AAPROPS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:25k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9. //--------------------------------------------------------------------------;
  10. //
  11. //  aaprops.c
  12. //
  13. //  Description:
  14. //      Get and display information on a .wav file and its format.
  15. //
  16. //
  17. //==========================================================================;
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <mmsystem.h>
  21. #include <memory.h>
  22. #include <mmreg.h>
  23. #include <msacm.h>
  24. #include "muldiv32.h"
  25. #include "appport.h"
  26. #include "acmapp.h"
  27. #include "debug.h"
  28. //==========================================================================;
  29. //
  30. //
  31. //
  32. //
  33. //==========================================================================;
  34. //--------------------------------------------------------------------------;
  35. //  
  36. //  BOOL AcmAppGetErrorString
  37. //  
  38. //  Description:
  39. //  
  40. //  
  41. //  Arguments:
  42. //      MMRESULT mmr:
  43. //  
  44. //      PTSTR psz:
  45. //  
  46. //  Return (BOOL):
  47. //  
  48. //  
  49. //--------------------------------------------------------------------------;
  50. BOOL FNGLOBAL AcmAppGetErrorString
  51. (
  52.     MMRESULT                mmr,
  53.     LPTSTR                  pszError
  54. )
  55. {
  56.     PTSTR               psz;
  57.     switch (mmr)
  58.     {
  59.         case MMSYSERR_NOERROR:
  60.             psz = TEXT("MMSYSERR_NOERROR");
  61.             break;
  62.         case MMSYSERR_ERROR:
  63.             psz = TEXT("MMSYSERR_ERROR");
  64.             break;
  65.         case MMSYSERR_BADDEVICEID:
  66.             psz = TEXT("MMSYSERR_BADDEVICEID");
  67.             break;
  68.         case MMSYSERR_NOTENABLED:
  69.             psz = TEXT("MMSYSERR_NOTENABLED");
  70.             break;
  71.         case MMSYSERR_ALLOCATED:
  72.             psz = TEXT("MMSYSERR_ALLOCATED");
  73.             break;
  74.         case MMSYSERR_INVALHANDLE:
  75.             psz = TEXT("MMSYSERR_INVALHANDLE");
  76.             break;
  77.         case MMSYSERR_NODRIVER:
  78.             psz = TEXT("MMSYSERR_NODRIVER");
  79.             break;
  80.         case MMSYSERR_NOMEM:
  81.             psz = TEXT("MMSYSERR_NOMEM");
  82.             break;
  83.         case MMSYSERR_NOTSUPPORTED:
  84.             psz = TEXT("MMSYSERR_NOTSUPPORTED");
  85.             break;
  86.         case MMSYSERR_BADERRNUM:
  87.             psz = TEXT("MMSYSERR_BADERRNUM");
  88.             break;
  89.         case MMSYSERR_INVALFLAG:
  90.             psz = TEXT("MMSYSERR_INVALFLAG");
  91.             break;
  92.         case MMSYSERR_INVALPARAM:
  93.             psz = TEXT("MMSYSERR_INVALPARAM");
  94.             break;
  95.         case WAVERR_BADFORMAT:
  96.             psz = TEXT("WAVERR_BADFORMAT");
  97.             break;
  98.         case WAVERR_STILLPLAYING:
  99.             psz = TEXT("WAVERR_STILLPLAYING");
  100.             break;
  101.         case WAVERR_UNPREPARED:
  102.             psz = TEXT("WAVERR_UNPREPARED");
  103.             break;
  104.         case WAVERR_SYNC:
  105.             psz = TEXT("WAVERR_SYNC");
  106.             break;
  107.         case ACMERR_NOTPOSSIBLE:
  108.             psz = TEXT("ACMERR_NOTPOSSIBLE");
  109.             break;
  110.         case ACMERR_BUSY:
  111.             psz = TEXT("ACMERR_BUSY");
  112.             break;
  113.         case ACMERR_UNPREPARED:
  114.             psz = TEXT("ACMERR_UNPREPARED");
  115.             break;
  116.         case ACMERR_CANCELED:
  117.             psz = TEXT("ACMERR_CANCELED");
  118.             break;
  119.         default:
  120.             lstrcpy(pszError, TEXT("(unknown)"));
  121.             return (FALSE);
  122.     }
  123.     lstrcpy(pszError, psz);
  124.     return (TRUE);
  125. } // AcmAppGetErrorString()
  126. //--------------------------------------------------------------------------;
  127. //  
  128. //  BOOL AcmAppGetFormatDescription
  129. //  
  130. //  Description:
  131. //  
  132. //  
  133. //  Arguments:
  134. //      LPWAVEFORMATEX pwfx:
  135. //  
  136. //      LPSTR pszFormatTag:
  137. //  
  138. //      LPSTR pszFormat:
  139. //  
  140. //  Return (BOOL):
  141. //  
  142. //  
  143. //--------------------------------------------------------------------------;
  144. TCHAR   gszIntl[]           = TEXT("Intl");
  145. TCHAR   gszIntlList[]       = TEXT("sList");
  146. TCHAR   gszIntlDecimal[]    = TEXT("sDecimal");
  147. TCHAR   gchIntlList         = ',';
  148. TCHAR   gchIntlDecimal      = '.';
  149. BOOL FNGLOBAL AcmAppGetFormatDescription
  150. (
  151.     LPWAVEFORMATEX          pwfx,
  152.     LPTSTR                  pszFormatTag,
  153.     LPTSTR                  pszFormat
  154. )
  155. {
  156.     MMRESULT            mmr;
  157.     BOOL                f;
  158.     f = TRUE;
  159.     //
  160.     //  get the name for the format tag of the specified format
  161.     //
  162.     if (NULL != pszFormatTag)
  163.     {
  164.         ACMFORMATTAGDETAILS aftd;
  165.         //
  166.         //  initialize all unused members of the ACMFORMATTAGDETAILS
  167.         //  structure to zero
  168.         //
  169.         memset(&aftd, 0, sizeof(aftd));
  170.         //
  171.         //  fill in the required members of the ACMFORMATTAGDETAILS
  172.         //  structure for the ACM_FORMATTAGDETAILSF_FORMATTAG query
  173.         //
  174.         aftd.cbStruct    = sizeof(aftd);
  175.         aftd.dwFormatTag = pwfx->wFormatTag;
  176.         //
  177.         //  ask the ACM to find the first available driver that
  178.         //  supports the specified format tag
  179.         //
  180.         mmr = acmFormatTagDetails(NULL,
  181.                                   &aftd,
  182.                                   ACM_FORMATTAGDETAILSF_FORMATTAG);
  183.         if (MMSYSERR_NOERROR == mmr)
  184.         {
  185.             //
  186.             //  copy the format tag name into the caller's buffer
  187.             //
  188.             lstrcpy(pszFormatTag, aftd.szFormatTag);
  189.         }
  190.         else
  191.         {
  192.             PTSTR           psz;
  193.             //
  194.             //  no ACM driver is available that supports the
  195.             //  specified format tag
  196.             //
  197.             f   = FALSE;
  198.             psz = NULL;
  199.             //
  200.             //  the following stuff if proof that the world does NOT need
  201.             //  yet another ADPCM algorithm!!
  202.             //
  203.             switch (pwfx->wFormatTag)
  204.             {
  205.                 case WAVE_FORMAT_UNKNOWN:
  206.                     psz = TEXT("** RESERVED INVALID TAG **");
  207.                     break;
  208.                 case WAVE_FORMAT_PCM:
  209.                     psz = TEXT("PCM");
  210.                     break;
  211.                 case WAVE_FORMAT_ADPCM:
  212.                     psz = TEXT("Microsoft ADPCM");
  213.                     break;
  214.                 case 0x0003:
  215.                     psz = TEXT("MV's *UNREGISTERED* ADPCM");
  216.                     break;
  217.                 case WAVE_FORMAT_IBM_CVSD:
  218.                     psz = TEXT("IBM CVSD");
  219.                     break;
  220.                 case WAVE_FORMAT_ALAW:
  221.                     psz = TEXT("A-Law");
  222.                     break;
  223.                 case WAVE_FORMAT_MULAW:
  224.                     psz = TEXT("u-Law");
  225.                     break;
  226.                 case WAVE_FORMAT_OKI_ADPCM:
  227.                     psz = TEXT("OKI ADPCM");
  228.                     break;
  229.                 case WAVE_FORMAT_IMA_ADPCM:
  230.                     psz = TEXT("IMA/DVI ADPCM");
  231.                     break;
  232.                 case WAVE_FORMAT_DIGISTD:
  233.                     psz = TEXT("DIGI STD");
  234.                     break;
  235.                 case WAVE_FORMAT_DIGIFIX:
  236.                     psz = TEXT("DIGI FIX");
  237.                     break;
  238.                 case WAVE_FORMAT_YAMAHA_ADPCM:
  239.                     psz = TEXT("Yamaha ADPCM");
  240.                     break;
  241.                 case WAVE_FORMAT_SONARC:
  242.                     psz = TEXT("Sonarc");
  243.                     break;
  244.                 case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
  245.                     psz = TEXT("DSP Group TrueSpeech");
  246.                     break;
  247.                 case WAVE_FORMAT_ECHOSC1:
  248.                     psz = TEXT("Echo SC1");
  249.                     break;
  250.                 case WAVE_FORMAT_AUDIOFILE_AF36:
  251.                     psz = TEXT("Audiofile AF36");
  252.                     break;
  253.                 case WAVE_FORMAT_CREATIVE_ADPCM:
  254.                     psz = TEXT("Creative Labs ADPCM");
  255.                     break;
  256.                 case WAVE_FORMAT_APTX:
  257.                     psz = TEXT("APTX");
  258.                     break;
  259.                 case WAVE_FORMAT_AUDIOFILE_AF10:
  260.                     psz = TEXT("Audiofile AF10");
  261.                     break;
  262.                 case WAVE_FORMAT_DOLBY_AC2:
  263.                     psz = TEXT("Dolby AC2");
  264.                     break;
  265.                 case WAVE_FORMAT_MEDIASPACE_ADPCM:
  266.                     psz = TEXT("Media Space ADPCM");
  267.                     break;
  268.                 case WAVE_FORMAT_SIERRA_ADPCM:
  269.                     psz = TEXT("Sierra ADPCM");
  270.                     break;
  271.                 case WAVE_FORMAT_G723_ADPCM:
  272.                     psz = TEXT("CCITT G.723 ADPCM");
  273.                     break;
  274.                 case WAVE_FORMAT_GSM610:
  275.                     psz = TEXT("GSM 6.10");
  276.                     break;
  277.                 case WAVE_FORMAT_G721_ADPCM:
  278.                     psz = TEXT("CCITT G.721 ADPCM");
  279.                     break;
  280.                 case WAVE_FORMAT_DEVELOPMENT:
  281.                     psz = TEXT("** RESERVED DEVELOPMENT ONLY TAG **");
  282.                     break;
  283.                 default:
  284.                     wsprintf(pszFormatTag, TEXT("[%u] (unknown)"), pwfx->wFormatTag);
  285.                     break;
  286.             }
  287.             if (NULL != psz)
  288.             {
  289.                 lstrcpy(pszFormatTag, psz);
  290.             }
  291.         }
  292.     }
  293.     //
  294.     //  get the description of the attributes for the specified
  295.     //  format
  296.     //
  297.     if (NULL != pszFormat)
  298.     {
  299.         ACMFORMATDETAILS    afd;
  300.         //
  301.         //  initialize all unused members of the ACMFORMATDETAILS
  302.         //  structure to zero
  303.         //
  304.         memset(&afd, 0, sizeof(afd));
  305.         //
  306.         //  fill in the required members of the ACMFORMATDETAILS
  307.         //  structure for the ACM_FORMATDETAILSF_FORMAT query
  308.         //
  309.         afd.cbStruct    = sizeof(afd);
  310.         afd.dwFormatTag = pwfx->wFormatTag;
  311.         afd.pwfx        = pwfx;
  312.         //
  313.         //  the cbwfx member must be initialized to the total size
  314.         //  in bytes needed for the specified format. for a PCM 
  315.         //  format, the cbSize member of the WAVEFORMATEX structure
  316.         //  is not valid.
  317.         //
  318.         if (WAVE_FORMAT_PCM == pwfx->wFormatTag)
  319.         {
  320.             afd.cbwfx   = sizeof(PCMWAVEFORMAT);
  321.         }
  322.         else
  323.         {
  324.             afd.cbwfx   = sizeof(WAVEFORMATEX) + pwfx->cbSize;
  325.         }
  326.         //
  327.         //  ask the ACM to find the first available driver that
  328.         //  supports the specified format
  329.         //
  330.         mmr = acmFormatDetails(NULL, &afd, ACM_FORMATDETAILSF_FORMAT);
  331.         if (MMSYSERR_NOERROR == mmr)
  332.         {
  333.             //
  334.             //  copy the format attributes description into the caller's
  335.             //  buffer
  336.             //
  337.             lstrcpy(pszFormat, afd.szFormat);
  338.         }
  339.         else
  340.         {
  341.             TCHAR           ach[2];
  342.             TCHAR           szChannels[24];
  343.             UINT            cBits;
  344.             //
  345.             //  no ACM driver is available that supports the
  346.             //  specified format
  347.             //
  348.             f = FALSE;
  349.             //
  350.             //
  351.             //
  352.             ach[0] = gchIntlList;
  353.             ach[1] = '';
  354.             GetProfileString(gszIntl, gszIntlList, ach, ach, sizeof(ach));
  355.             gchIntlList = ach[0];
  356.             ach[0] = gchIntlDecimal;
  357.             ach[1] = '';
  358.             GetProfileString(gszIntl, gszIntlDecimal, ach, ach, sizeof(ach));
  359.             gchIntlDecimal = ach[0];
  360.             //
  361.             //  compute the bit depth--this _should_ be the same as
  362.             //  wBitsPerSample, but isn't always...
  363.             //
  364.             cBits = (UINT)(pwfx->nAvgBytesPerSec * 8 /
  365.                            pwfx->nSamplesPerSec /
  366.                            pwfx->nChannels);
  367.             if ((1 == pwfx->nChannels) || (2 == pwfx->nChannels))
  368.             {
  369.                 if (1 == pwfx->nChannels)
  370.                     lstrcpy(szChannels, TEXT("Mono"));
  371.                 else
  372.                     lstrcpy(szChannels, TEXT("Stereo"));
  373.                 wsprintf(pszFormat, TEXT("%lu%c%.03u kHz%c %u Bit%c %s"),
  374.                             pwfx->nSamplesPerSec / 1000,
  375.                             gchIntlDecimal,
  376.                             (UINT)(pwfx->nSamplesPerSec % 1000),
  377.                             gchIntlList,
  378.                             cBits,
  379.                             gchIntlList,
  380.                             (LPTSTR)szChannels);
  381.             }
  382.             else
  383.             {
  384.                 wsprintf(pszFormat, TEXT("%lu%c%.03u kHz%c %u Bit%c %u Channels"),
  385.                             pwfx->nSamplesPerSec / 1000,
  386.                             gchIntlDecimal,
  387.                             (UINT)(pwfx->nSamplesPerSec % 1000),
  388.                             gchIntlList,
  389.                             cBits,
  390.                             gchIntlList,
  391.                             pwfx->nChannels);
  392.             }
  393.         }
  394.     }
  395.     //
  396.     //
  397.     //
  398.     return (f);
  399. } // AcmAppGetFormatDescription()
  400. //--------------------------------------------------------------------------;
  401. //  
  402. //  BOOL AcmAppGetFilterDescription
  403. //  
  404. //  Description:
  405. //  
  406. //  
  407. //  Arguments:
  408. //      LPWAVEFILTER pwfltr:
  409. //  
  410. //      LPSTR pszFilterTag:
  411. //  
  412. //      LPSTR pszFilter:
  413. //  
  414. //  Return (BOOL):
  415. //  
  416. //  
  417. //--------------------------------------------------------------------------;
  418. BOOL FNGLOBAL AcmAppGetFilterDescription
  419. (
  420.     LPWAVEFILTER            pwfltr,
  421.     LPTSTR                  pszFilterTag,
  422.     LPTSTR                  pszFilter
  423. )
  424. {
  425.     MMRESULT            mmr;
  426.     BOOL                f;
  427.     f = TRUE;
  428.     //
  429.     //  get the name for the filter tag of the specified filter
  430.     //
  431.     if (NULL != pszFilterTag)
  432.     {
  433.         ACMFILTERTAGDETAILS aftd;
  434.         //
  435.         //  initialize all unused members of the ACMFILTERTAGDETAILS
  436.         //  structure to zero
  437.         //
  438.         memset(&aftd, 0, sizeof(aftd));
  439.         //
  440.         //  fill in the required members of the ACMFILTERTAGDETAILS
  441.         //  structure for the ACM_FILTERTAGDETAILSF_FILTERTAG query
  442.         //
  443.         aftd.cbStruct    = sizeof(aftd);
  444.         aftd.dwFilterTag = pwfltr->dwFilterTag;
  445.         //
  446.         //  ask the ACM to find the first available driver that
  447.         //  supports the specified filter tag
  448.         //
  449.         mmr = acmFilterTagDetails(NULL,
  450.                                   &aftd,
  451.                                   ACM_FILTERTAGDETAILSF_FILTERTAG);
  452.         if (MMSYSERR_NOERROR == mmr)
  453.         {
  454.             //
  455.             //  copy the filter tag name into the caller's buffer
  456.             //
  457.             lstrcpy(pszFilterTag, aftd.szFilterTag);
  458.         }
  459.         else
  460.         {
  461.             PTSTR           psz;
  462.             psz = NULL;
  463.             f   = FALSE;
  464.             //
  465.             //  no ACM driver is available that supports the
  466.             //  specified filter tag
  467.             //
  468.             switch (pwfltr->dwFilterTag)
  469.             {
  470.                 case WAVE_FILTER_UNKNOWN:
  471.                     psz = TEXT("** RESERVED INVALID TAG **");
  472.                     break;
  473.                 case WAVE_FILTER_VOLUME:
  474.                     psz = TEXT("Microsoft Volume Filter");
  475.                     break;
  476.                 case WAVE_FILTER_ECHO:
  477.                     psz = TEXT("Microsoft Echo Filter");
  478.                     break;
  479.                 case WAVE_FILTER_DEVELOPMENT:
  480.                     psz = TEXT("** RESERVED DEVELOPMENT ONLY TAG **");
  481.                     break;
  482.                 default:
  483.                     wsprintf(pszFilterTag, TEXT("[%lu] (unknown)"),pwfltr->dwFilterTag);
  484.                     break;
  485.             }
  486.             if (NULL != psz)
  487.             {
  488.                 lstrcpy(pszFilterTag, psz);
  489.             }
  490.         }
  491.     }
  492.     //
  493.     //  get the description of the attributes for the specified
  494.     //  filter
  495.     //
  496.     if (NULL != pszFilter)
  497.     {
  498.         ACMFILTERDETAILS    afd;
  499.         //
  500.         //  initialize all unused members of the ACMFILTERDETAILS
  501.         //  structure to zero
  502.         //
  503.         memset(&afd, 0, sizeof(afd));
  504.         //
  505.         //  fill in the required members of the ACMFILTERDETAILS
  506.         //  structure for the ACM_FILTERDETAILSF_FILTER query
  507.         //
  508.         afd.cbStruct    = sizeof(afd);
  509.         afd.dwFilterTag = pwfltr->dwFilterTag;
  510.         afd.pwfltr      = pwfltr;
  511.         afd.cbwfltr     = pwfltr->cbStruct;
  512.         //
  513.         //  ask the ACM to find the first available driver that
  514.         //  supports the specified filter
  515.         //
  516.         mmr = acmFilterDetails(NULL, &afd, ACM_FILTERDETAILSF_FILTER);
  517.         if (MMSYSERR_NOERROR == mmr)
  518.         {
  519.             //
  520.             //  copy the filter attributes description into the caller's
  521.             //  buffer
  522.             //
  523.             lstrcpy(pszFilter, afd.szFilter);
  524.         }
  525.         else
  526.         {
  527.             //
  528.             //  no ACM driver is available that supports the
  529.             //  specified filter
  530.             //
  531.             f = FALSE;
  532.             wsprintf(pszFilter, TEXT("Unknown Filter %lu, %.08lXh"),
  533.                         pwfltr->dwFilterTag, pwfltr->fdwFilter);
  534.         }
  535.     }
  536.     //
  537.     //
  538.     //
  539.     return (f);
  540. } // AcmAppGetFilterDescription()
  541. //--------------------------------------------------------------------------;
  542. //  
  543. //  BOOL AcmAppDumpExtraHeaderData
  544. //  
  545. //  Description:
  546. //  
  547. //  
  548. //  Arguments:
  549. //      HWND hedit:
  550. //  
  551. //      LPWAVEFORMATEX pwfx:
  552. //  
  553. //  Return (BOOL):
  554. //  
  555. //  
  556. //--------------------------------------------------------------------------;
  557. BOOL FNLOCAL AcmAppDumpExtraHeaderData
  558. (
  559.     HWND            hedit,
  560.     LPWAVEFORMATEX  pwfx
  561. )
  562. {
  563.     static TCHAR    szDisplayTitle[]  = TEXT("Offset Data Bytes");
  564.     if ((WAVE_FORMAT_PCM == pwfx->wFormatTag) || (0 == pwfx->cbSize))
  565.         return (TRUE);
  566.     MEditPrintF(hedit, szDisplayTitle);
  567.     MEditPrintF(hedit, TEXT("------ -----------------------------------------------"));
  568.     //
  569.     //  !!! this is really horrible code !!!
  570.     //
  571. {
  572.     #define ACMAPP_DUMP_BYTES_PER_LINE  16
  573.     UINT    u;
  574.     UINT    v;
  575.     for (u = 0; u < pwfx->cbSize; u += ACMAPP_DUMP_BYTES_PER_LINE)
  576.     {
  577.         MEditPrintF(hedit, TEXT("~0x%.04X"), u);
  578.         for (v = 0; v < ACMAPP_DUMP_BYTES_PER_LINE; v++)
  579.         {
  580.             if ((u + v) >= pwfx->cbSize)
  581.                 break;
  582.             MEditPrintF(hedit, TEXT("~ %.02X"), ((LPBYTE)(pwfx + 1))[u + v]);
  583.         }
  584.         MEditPrintF(hedit, gszNull);
  585.     }
  586.     #undef ACMAPP_DUMP_BYTES_PER_LINE
  587. }
  588.     return (TRUE);
  589. } // AcmAppDumpExtraHeaderData()
  590. //--------------------------------------------------------------------------;
  591. //  
  592. //  BOOL AcmAppDisplayFileProperties
  593. //  
  594. //  Description:
  595. //  
  596. //  
  597. //  Arguments:
  598. //      HWND hwnd:
  599. //  
  600. //      PACMAPPFILEDESC paafd:
  601. //  
  602. //  Return (BOOL):
  603. //  
  604. //--------------------------------------------------------------------------;
  605. BOOL FNGLOBAL AcmAppDisplayFileProperties
  606. (
  607.     HWND            hwnd,
  608.     PACMAPPFILEDESC paafd
  609. )
  610. {
  611.     static TCHAR    szInvalidWaveFile[] = TEXT("No File");
  612.     static TCHAR    szDisplayTitle[]    = TEXT("[Wave File Format Properties]rn");
  613.     MMRESULT        mmr;
  614.     TCHAR           szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
  615.     TCHAR           ach[APP_MAX_STRING_CHARS];
  616.     DWORD           dw;
  617.     LPWAVEFORMATEX  pwfx;
  618.     HWND            hedit;
  619.     HMENU           hmenu;
  620.     BOOL            fCanPlayRecord;
  621.     BOOL            f;
  622.     //
  623.     //  clear the display
  624.     //
  625.     AppHourGlass(TRUE);
  626.     hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
  627.     SetWindowRedraw(hedit, FALSE);
  628.     MEditPrintF(hedit, NULL);
  629.     //
  630.     //
  631.     //
  632.     MEditPrintF(hedit, szDisplayTitle);
  633.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Title"), (LPTSTR)paafd->szFileTitle);
  634.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Full Path"), (LPTSTR)paafd->szFilePath);
  635.     AppFormatBigNumber(ach, paafd->cbFileSize);
  636.     MEditPrintF(hedit, TEXT("%25s: %s bytes"), (LPTSTR)TEXT("Total File Size"), (LPTSTR)ach);
  637.     AppFormatDosDateTime(ach, paafd->uDosChangeDate, paafd->uDosChangeTime);
  638.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Last Change Date/Time"), (LPTSTR)ach);
  639.     dw = paafd->fdwFileAttributes;
  640.     MEditPrintF(hedit, TEXT("%25s: %c %c%c%c%c %c%c%c%c (%.08lXh)"),
  641.                     (LPTSTR)TEXT("Attributes"),
  642.                     (dw & FILE_ATTRIBUTE_TEMPORARY) ? 't' : '-',
  643.                     (dw & FILE_ATTRIBUTE_NORMAL)    ? 'n' : '-',
  644.                     (dw & 0x00000040)               ? '?' : '-',
  645.                     (dw & FILE_ATTRIBUTE_ARCHIVE)   ? 'a' : '-',
  646.                     (dw & FILE_ATTRIBUTE_DIRECTORY) ? 'd' : '-',
  647.                     (dw & 0x00000008)               ? '?' : '-',
  648.                     (dw & FILE_ATTRIBUTE_SYSTEM)    ? 's' : '-',
  649.                     (dw & FILE_ATTRIBUTE_HIDDEN)    ? 'h' : '-',
  650.                     (dw & FILE_ATTRIBUTE_READONLY)  ? 'r' : '-',
  651.                     dw);
  652.     pwfx = paafd->pwfx;
  653.     if (NULL == pwfx)
  654.     {
  655.         fCanPlayRecord = FALSE;
  656.         goto AA_Display_File_Properties_Exit;
  657.     }
  658.     //
  659.     //
  660.     //
  661.     //
  662.     f = AcmAppGetFormatDescription(pwfx, szFormatTag, ach);
  663.     MEditPrintF(hedit, TEXT("rn%25s: %s%s"), (LPTSTR)TEXT("Format"),
  664.                 f ? (LPTSTR)gszNull : (LPTSTR)TEXT("*"),
  665.                 (LPTSTR)szFormatTag);
  666.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Attributes"), (LPTSTR)ach);
  667.     AppFormatBigNumber(ach, paafd->dwDataBytes);
  668.     MEditPrintF(hedit, TEXT("rn%25s: %s bytes"), (LPTSTR)TEXT("Data Size"), (LPTSTR)ach);
  669.     AppFormatBigNumber(ach, paafd->dwDataBytes / pwfx->nAvgBytesPerSec);
  670.     dw = paafd->dwDataBytes % pwfx->nAvgBytesPerSec;
  671.     dw = (dw * 1000) / pwfx->nAvgBytesPerSec;
  672.     MEditPrintF(hedit, TEXT("%25s: %s.%.03lu seconds"), (LPTSTR)TEXT("Play Time (avg bytes)"), (LPTSTR)ach, dw);
  673.     AppFormatBigNumber(ach, paafd->dwDataSamples);
  674.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Total Samples"), (LPTSTR)ach);
  675.     AppFormatBigNumber(ach, paafd->dwDataSamples / pwfx->nSamplesPerSec);
  676.     dw = paafd->dwDataSamples % pwfx->nSamplesPerSec;
  677.     dw = (dw * 1000) / pwfx->nSamplesPerSec;
  678.     MEditPrintF(hedit, TEXT("%25s: %s.%.03lu seconds"), (LPTSTR)TEXT("Play Time (samples)"), (LPTSTR)ach, dw);
  679.     //
  680.     //
  681.     //
  682.     MEditPrintF(hedit, TEXT("rn%25s: %u"), (LPTSTR)TEXT("Format Tag"), pwfx->wFormatTag);
  683.     MEditPrintF(hedit, TEXT("%25s: %u"), (LPTSTR)TEXT("Channels"), pwfx->nChannels);
  684.     AppFormatBigNumber(ach, pwfx->nSamplesPerSec);
  685.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Samples Per Second"), (LPTSTR)ach);
  686.     AppFormatBigNumber(ach, pwfx->nAvgBytesPerSec);
  687.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Avg Bytes Per Second"), (LPTSTR)ach);
  688.     AppFormatBigNumber(ach, pwfx->nBlockAlign);
  689.     MEditPrintF(hedit, TEXT("%25s: %s"), (LPTSTR)TEXT("Block Alignment"), (LPTSTR)ach);
  690.     MEditPrintF(hedit, TEXT("%25s: %u"), (LPTSTR)TEXT("Bits Per Sample"), pwfx->wBitsPerSample);
  691.     if (WAVE_FORMAT_PCM != pwfx->wFormatTag)
  692.     {
  693.         AppFormatBigNumber(ach, pwfx->cbSize);
  694.         MEditPrintF(hedit, TEXT("%25s: %s bytesrn"), (LPTSTR)TEXT("Extra Format Information"), (LPTSTR)ach);
  695.         AcmAppDumpExtraHeaderData(hedit, pwfx);
  696.     }
  697.     //
  698.     //  note that we do NOT set the 'WAVE_ALLOWSYNC' bit on queries because
  699.     //  the player/recorder dialog uses MCIWAVE--which cannot work with
  700.     //  SYNC devices.
  701.     //
  702.     mmr = waveOutOpen(NULL,
  703.                       guWaveOutId,
  704. #if (WINVER < 0x0400)
  705.                       (LPWAVEFORMAT)pwfx,
  706. #else
  707.                       pwfx,
  708. #endif
  709.                       0L, 0L, WAVE_FORMAT_QUERY);
  710.     fCanPlayRecord = (MMSYSERR_NOERROR == mmr);
  711.     if (!fCanPlayRecord)
  712.     {
  713.         //
  714.         //  this situation can happen with the 'preferred' device settings
  715.         //  for the Sound Mapper.
  716.         //
  717.         mmr = waveInOpen(NULL,
  718.                          guWaveInId,
  719. #if (WINVER < 0x0400)
  720.                          (LPWAVEFORMAT)pwfx,
  721. #else
  722.                          pwfx,
  723. #endif
  724.                          0L, 0L, WAVE_FORMAT_QUERY);
  725.         fCanPlayRecord = (MMSYSERR_NOERROR == mmr);
  726.     }
  727. AA_Display_File_Properties_Exit:
  728.     hmenu = GetMenu(hwnd);
  729.     EnableMenuItem(hmenu, IDM_PLAYRECORD,
  730.                    MF_BYCOMMAND | (fCanPlayRecord ? MF_ENABLED : MF_GRAYED));
  731.     DrawMenuBar(hwnd);
  732.     Edit_SetSel(hedit, (WPARAM)0, (LPARAM)0);
  733.     SetWindowRedraw(hedit, TRUE);
  734.     AppHourGlass(FALSE);
  735.     return (fCanPlayRecord);
  736. } // AcmAppDisplayFileProperties()