home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / acmapp / aaprops.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  25KB  |  901 lines

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