home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / waveconv / waveconv.c < prev    next >
C/C++ Source or Header  |  1992-09-12  |  39KB  |  1,624 lines

  1. /** waveconv.c
  2.  *
  3.      (C) Copyright Microsoft Corp. 1991, 1992.  All rights reserved.
  4.  
  5.      You have a royalty-free right to use, modify, reproduce and 
  6.      distribute the Sample Files (and/or any modified version) in 
  7.      any way you find useful, provided that you agree that 
  8.      Microsoft has no warranty obligations or liability for any 
  9.      Sample Application Files which are modified. 
  10.      
  11.      If you did not get this from Microsoft Sources, then it may not be the
  12.      most current version.  This sample code in particular will be updated
  13.      and include more documentation.  
  14.  
  15.      Sources are:
  16.          The MM Sys File Transfer BBS: The phone number is 206 936-4082.
  17.     CompuServe: WINSDK forum, MDK section.
  18.     Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
  19.  *
  20.  *
  21.  **/
  22.  
  23.  
  24. //
  25. //  the includes we need
  26. //
  27. #define STRICT
  28. #include <windows.h>
  29. #include <commdlg.h>
  30. #include <shellapi.h>
  31. #include <windowsx.h>
  32. #include <memory.h>
  33. #include <mmsystem.h>
  34. #include <mmreg.h>
  35. #include "pcm.h"
  36. #include "msadpcm.h"
  37. #include "waveconv.h"
  38. #include "riffsup.h"
  39. #include "wavesup.h"
  40. #include "waveio.h"
  41.  
  42.  
  43. #if (_MSC_VER < 700)
  44. //
  45. //  this silly stuff is to get around a bug in the C6 compiler's optimizer
  46. //
  47. #ifdef GlobalFreePtr
  48. #undef GlobalFreePtr
  49. #define GlobalFreePtr(x)    GlobalFree((HGLOBAL)SELECTOROF(x))
  50. #endif
  51.  
  52. #endif
  53.  
  54. typedef DWORD (FAR PASCAL *CONVERTPROC)(LPWAVEFORMATEX, HPSTR, LPWAVEFORMATEX, HPSTR, DWORD);
  55.  
  56. typedef struct tWAVECONVCB
  57. {
  58.     HMMIO           hmmioSrc;
  59.     HMMIO           hmmioDst;
  60.  
  61.     MMCKINFO        ckDst;
  62.     MMCKINFO        ckDstRIFF;
  63.  
  64.     DWORD           dwSrcSamples;
  65.     DWORD           dwSrcReadSize;
  66.  
  67.     DWORD           dwDstBufSize;
  68.  
  69.     LPSTR           lpszFilePathSrc;
  70.     LPWAVEFORMATEX  lpwfxSrc;
  71.     HPSTR           hpSrc;
  72.     DWORD           dwSrcBytes;
  73.     LPSTR           lpszFilePathDst;
  74.     LPWAVEFORMATEX  lpwfxDst;
  75.     HPSTR           hpDst;
  76.     CONVERTPROC     fpConvert;
  77.  
  78. } WAVECONVCB, *PWAVECONVCB, FAR *LPWAVECONVCB;
  79.  
  80.  
  81. //
  82. //  flags for AppGetFileName()...
  83. //
  84. #define AGFN_FLAG_OPEN      0x0000
  85. #define AGFN_FLAG_SAVE      0x0001
  86.  
  87. //
  88. //  prototypes for good measure
  89. //
  90. BOOL FAR PASCAL DlgProcConvert(HWND, UINT, WPARAM, LPARAM);
  91. BOOL FAR PASCAL DlgProcAbout(HWND, UINT, WPARAM, LPARAM);
  92. LRESULT FAR PASCAL WndProcApp(HWND, UINT, WPARAM, LPARAM);
  93.  
  94. //
  95. //  globals, no less
  96. //
  97.  
  98. WAVECONVCB      gwc;
  99.  
  100.  
  101. char            gszAppName[]        = "Microsoft Wave Converter";
  102. HINSTANCE       ghInstance;
  103. HWND            ghwnd;
  104.  
  105. BOOL            gfCancelConvert;
  106.  
  107. char            gszNone[]           = "(none)";
  108. char            gszUnknown[]        = "(unknown)";
  109.  
  110.  
  111. LPWAVEIOCB      glpwio=NULL;
  112. LPWAVEFORMATEX  glpwfx=NULL;
  113. char            gszWaveFilePath[MAX_FILE_PATH_LEN];
  114. char            gszWaveFormat[MAX_FORMAT_LEN];
  115.  
  116. char            gszSaveFilePath[MAX_FILE_PATH_LEN];
  117.  
  118. static        LPSTR lpplayerr="Error Playing File: %s";
  119.  
  120. //
  121. //
  122. //
  123. //
  124. #define WM_CONVERT_BEGIN    (WM_USER + 100)
  125. #define WM_CONVERT_END      (WM_USER + 101)
  126.  
  127. /* void Cls_OnConvertBegin(HWND hwnd, WAVECONVCB FAR* lpwc) */
  128. #define HANDLE_WM_CONVERT_BEGIN(hwnd, wParam, lParam, fn) \
  129.     ((fn)((hwnd), (WAVECONVCB FAR*)(lParam)), 0L)
  130. #define FORWARD_WM_CONVERT_BEGIN(hwnd, lpwc, fn) \
  131.     (void)(fn)((hwnd), WM_CONVERT_BEGIN, 0, (LPARAM)(WAVECONVCB FAR*)(lpwc))
  132.  
  133. /* void Cls_OnConvertEnd(HWND hwnd, BOOL fCancel, WAVECONVCB FAR* lpwc) */
  134. #define HANDLE_WM_CONVERT_END(hwnd, wParam, lParam, fn) \
  135.     ((fn)((hwnd), (BOOL)(wParam), (WAVECONVCB FAR*)(lParam)), 0L)
  136. #define FORWARD_WM_CONVERT_END(hwnd, fCancel, lpwc, fn) \
  137.     (void)(fn)((hwnd), WM_CONVERT_END, (WPARAM)(fCancel), (LPARAM)(WAVECONVCB FAR*)(lpwc))
  138.  
  139. #define    BeginConvert(hwnd, lpwc)    FORWARD_WM_CONVERT_BEGIN((hwnd), (lpwc), PostMessage)
  140. #define    EndConvert(hwnd, fCancel, lpwc)    FORWARD_WM_CONVERT_END((hwnd), (fCancel), (lpwc), PostMessage)
  141.  
  142.  
  143. /** void FAR _cdecl AppErrorMsg(LPSTR sz, ...)
  144.  *
  145.  *  DESCRIPTION:
  146.  *      
  147.  *
  148.  *  ARGUMENTS:
  149.  *      (LPSTR sz, ...)
  150.  *
  151.  *  RETURN (void):
  152.  *
  153.  *
  154.  *  NOTES:
  155.  *
  156.  ** */
  157.  
  158. void FAR _cdecl AppErrorMsg(HWND hwnd, LPCSTR lpszFormat, ...)
  159. {
  160.     char    ach[MAX_ERR_LEN];
  161.  
  162.     //
  163.     //  format and display the string in a message box...
  164.     //
  165.     wvsprintf(ach, lpszFormat, (LPSTR)(&lpszFormat+1));
  166.     MessageBox(hwnd, ach, gszAppName, MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  167. } /* AppErrorMsg() */
  168.  
  169.  
  170. /** void NEAR PASCAL AppDlgYield(HWND hdlg)
  171.  *
  172.  *  DESCRIPTION:
  173.  *      Yield function for modeless dialogs...
  174.  *
  175.  *  ARGUMENTS:
  176.  *      (HWND hdlg)
  177.  *
  178.  *  RETURN (void NEAR PASCAL):
  179.  *
  180.  *
  181.  *  NOTES:
  182.  *
  183.  ** */
  184.  
  185. void NEAR PASCAL AppDlgYield(HWND hdlg)
  186. {
  187.     MSG     msg;
  188.  
  189.     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  190.     {
  191.         if ((hdlg == NULL) || !IsDialogMessage(hdlg, &msg))
  192.         {
  193.             TranslateMessage(&msg);
  194.             DispatchMessage(&msg);
  195.         }
  196.     }
  197. } /* AppDlgYield() */
  198.  
  199.  
  200. /** void NEAR PASCAL AppHourGlass(BOOL fHourGlass)
  201.  *
  202.  *  DESCRIPTION: 
  203.  *      This function changes the cursor to that of the hour glass or
  204.  *      back to the previous cursor.
  205.  *
  206.  *  ARGUMENTS:
  207.  *      BOOL fHourGlass :   TRUE if we need the hour glass.  FALSE if
  208.  *                          we need the arrow back.
  209.  *
  210.  *  RETURN (void):
  211.  *      On return, the cursor will be what was requested.
  212.  *
  213.  *  NOTES:
  214.  *      This function can be called recursively.
  215.  *
  216.  ** */
  217.  
  218. void NEAR PASCAL AppHourGlass(BOOL fHourGlass)
  219. {
  220.     static HCURSOR  hCursor;
  221.     static WORD     wWaiting = 0;
  222.  
  223.     if (fHourGlass)
  224.     {
  225.         if (!wWaiting)
  226.         {
  227.             hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  228.             ShowCursor(TRUE);
  229.         }
  230.  
  231.         wWaiting++;
  232.     }
  233.     else
  234.     {
  235.         if (!--wWaiting)
  236.         {
  237.             ShowCursor(FALSE);
  238.             SetCursor(hCursor);
  239.         }
  240.     }
  241. } /* AppHourGlass() */
  242.  
  243.  
  244. /** BOOL NEAR PASCAL AppGetFileName(HWND hwnd, LPSTR lpszFilePath, LPSTR lpszFileTitle, WORD wFlags)
  245.  *
  246.  *  DESCRIPTION:
  247.  *      
  248.  *
  249.  *  ARGUMENTS:
  250.  *      (HWND hwnd, LPSTR lpszFilePath, LPSTR lpszFileTitle, WORD wFlags)
  251.  *
  252.  *  RETURN (BOOL NEAR PASCAL):
  253.  *
  254.  *
  255.  *  NOTES:
  256.  *
  257.  ** */
  258.  
  259. BOOL NEAR PASCAL AppGetFileName(HWND hwnd, LPSTR lpszFilePath, LPSTR lpszFileTitle, WORD wFlags)
  260. {
  261.     static char szDefExtension[]    = "WAV";
  262.     static char *szExtFilter[]      =
  263.     {
  264.         "Sound Files (*.wav)", "*.wav",
  265.         "All Files (*.*)", "*.*",
  266.         ""
  267.     };
  268.  
  269.     OPENFILENAME    ofn;
  270.  
  271.     _fmemset(&ofn, 0, sizeof(OPENFILENAME));
  272.     
  273.     //
  274.     //  initialize the OPENFILENAME members
  275.     //
  276.     lpszFilePath[0]         = '\0';
  277.     if (lpszFileTitle)
  278.         lpszFileTitle[0]    = '\0';
  279.  
  280.     ofn.lStructSize         = sizeof(OPENFILENAME);
  281.     ofn.hwndOwner           = hwnd;
  282.     ofn.lpstrFilter         = szExtFilter[0];
  283.     ofn.lpstrCustomFilter   = (LPSTR)NULL;
  284.     ofn.nMaxCustFilter      = 0L;
  285.     ofn.nFilterIndex        = 1L;
  286.     ofn.lpstrFile           = lpszFilePath;
  287.     ofn.nMaxFile            = MAX_FILE_PATH_LEN;
  288.     ofn.lpstrFileTitle      = lpszFileTitle;
  289.     ofn.nMaxFileTitle       = lpszFileTitle ? MAX_FILE_TITLE_LEN : 0;
  290.     ofn.lpstrInitialDir     = (LPSTR)NULL;
  291.     ofn.nFileOffset         = 0;
  292.     ofn.nFileExtension      = 0;
  293.     ofn.lpstrDefExt         = szDefExtension;
  294.  
  295.     if (wFlags == AGFN_FLAG_OPEN)
  296.     {
  297.         ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  298.         return (GetOpenFileName(&ofn));
  299.     }
  300.     else
  301.     {
  302.         ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
  303.         return (GetSaveFileName(&ofn));
  304.     }
  305. } /* AppGetFileName() */
  306.  
  307.  
  308. /** BOOL FAR PASCAL AppDialogBox(HWND hwnd, LPCSTR lpszDlg, DLGPROC lpfn, LPARAM lParam)
  309.  *
  310.  *  DESCRIPTION:
  311.  *      
  312.  *
  313.  *  ARGUMENTS:
  314.  *      (HWND hwnd, LPCSTR lpszDlg, DLGPROC lpfn, LPARAM lParam)
  315.  *
  316.  *  RETURN (BOOL NEAR PASCAL):
  317.  *
  318.  *
  319.  *  NOTES:
  320.  *
  321.  ** */
  322.  
  323. BOOL FAR PASCAL AppDialogBox(HWND hwnd, LPCSTR lpszDlg, DLGPROC lpfn, LPARAM lParam)
  324. {
  325.     BOOL    f;
  326.  
  327.     f = FALSE;
  328.     if (lpfn = (DLGPROC)MakeProcInstance((FARPROC)lpfn, ghInstance))
  329.     {
  330.         f = DialogBoxParam(ghInstance, lpszDlg, hwnd, lpfn, lParam);
  331.         FreeProcInstance((FARPROC)lpfn);
  332.     }
  333.  
  334.     return (f);
  335. } /* AppDialogBox() */
  336.  
  337.  
  338.  
  339. /** BOOL NEAR PASCAL WaveConvEnd(HWND hdlg, LPWAVECONVCB lpwc)
  340.  *
  341.  *  DESCRIPTION:
  342.  *      
  343.  *
  344.  *  ARGUMENTS:
  345.  *      (HWND hdlg, LPWAVECONVCB lpwc)
  346.  *
  347.  *  RETURN (BOOL NEAR PASCAL):
  348.  *
  349.  *
  350.  *  NOTES:
  351.  *
  352.  ** */
  353.  
  354. BOOL NEAR PASCAL WaveConvEnd(HWND hdlg, LPWAVECONVCB lpwc)
  355. {
  356.     if (lpwc->hmmioSrc)
  357.     {
  358.         mmioClose(lpwc->hmmioSrc, 0);
  359.         lpwc->hmmioSrc = NULL;
  360.     }
  361.  
  362.     if (lpwc->hmmioDst)
  363.     {
  364.         mmioAscend(lpwc->hmmioDst, &lpwc->ckDst, 0);
  365.         mmioAscend(lpwc->hmmioDst, &lpwc->ckDstRIFF, 0);
  366.  
  367.         mmioClose(lpwc->hmmioDst, 0);
  368.         lpwc->hmmioDst = NULL;
  369.     }
  370.  
  371.     if (lpwc->hpSrc)
  372.     {
  373.         GlobalFreePtr(lpwc->hpSrc);
  374.         lpwc->hpSrc = NULL;
  375.     }
  376.     
  377.     if (lpwc->hpDst)
  378.     {
  379.         GlobalFreePtr(lpwc->hpDst);
  380.         lpwc->hpDst = NULL;
  381.     }
  382.  
  383.     return (TRUE);
  384. } /* WaveConvEnd() */
  385.  
  386.  
  387. /** BOOL NEAR PASCAL WaveConvBegin(HWND hdlg, LPWAVECONVCB lpwc)
  388.  *
  389.  *  DESCRIPTION:
  390.  *      
  391.  *
  392.  *  ARGUMENTS:
  393.  *      (HWND hdlg, LPWAVECONVCB lpwc)
  394.  *
  395.  *  RETURN (BOOL NEAR PASCAL):
  396.  *
  397.  *
  398.  *  NOTES:
  399.  *
  400.  ** */
  401.  
  402. BOOL NEAR PASCAL WaveConvBegin(HWND hdlg, LPWAVECONVCB lpwc)
  403. {
  404.     MMCKINFO    ckSrcRIFF;
  405.     MMCKINFO    ck;
  406.     DWORD       dw;
  407.  
  408.     //
  409.     //  allocate the src and dst buffers for reading/converting data
  410.     //
  411.     lpwc->hpSrc = (HPSTR)GlobalAllocPtr(GHND, lpwc->dwSrcReadSize);
  412.     if (!lpwc->hpSrc)
  413.         goto wcb_Error;
  414.     
  415.     lpwc->hpDst = (HPSTR)GlobalAllocPtr(GHND, lpwc->dwDstBufSize);
  416.     if (!lpwc->hpDst)
  417.         goto wcb_Error;
  418.  
  419.     //
  420.     //
  421.     //
  422.     lpwc->hmmioDst = mmioOpen(lpwc->lpszFilePathDst, NULL, MMIO_CREATE | MMIO_WRITE | MMIO_ALLOCBUF);
  423.     if (!lpwc->hmmioDst)
  424.         goto wcb_Error;
  425.  
  426.     //
  427.     //  create the RIFF chunk of form type 'WAVE'
  428.     //
  429.     //
  430.     lpwc->ckDstRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  431.     lpwc->ckDstRIFF.cksize  = 0L;
  432.     if (mmioCreateChunk(lpwc->hmmioDst, &lpwc->ckDstRIFF, MMIO_CREATERIFF))
  433.         goto wcb_Error;
  434.  
  435.     //
  436.     //  first try to open the file, etc.. open the given file for reading
  437.     //  using buffered I/O
  438.     //
  439.     lpwc->hmmioSrc = mmioOpen(lpwc->lpszFilePathSrc, NULL, MMIO_READ | MMIO_ALLOCBUF);
  440.     if (!lpwc->hmmioSrc)
  441.         goto wcb_Error;
  442.  
  443.     //
  444.     //  locate a 'WAVE' form type in a 'RIFF' thing...
  445.     //
  446.     ckSrcRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  447.     if (mmioDescend(lpwc->hmmioSrc, (LPMMCKINFO)&ckSrcRIFF, NULL, MMIO_FINDRIFF))
  448.         goto wcb_Error;
  449.  
  450.     //
  451.     //  we found a WAVE chunk--now go through and get all subchunks that
  452.     //  we know how to deal with...
  453.     //
  454.     while (mmioDescend(lpwc->hmmioSrc, &ck, &ckSrcRIFF, 0) == 0)
  455.     {
  456.         //
  457.         //  quickly check for corrupt RIFF file--don't ascend past end!
  458.         //
  459.         if ((ck.dwDataOffset + ck.cksize) > (ckSrcRIFF.dwDataOffset + ckSrcRIFF.cksize))
  460.             goto wcb_Error;
  461.  
  462.         switch (ck.ckid)
  463.         {
  464.     // explicitly skip these...
  465.         
  466.             case mmioFOURCC('f', 'm', 't', ' '):
  467.                 break;
  468.  
  469.             case mmioFOURCC('d', 'a', 't', 'a'):
  470.                 break;
  471.  
  472.             case mmioFOURCC('f', 'a', 'c', 't'):
  473.                 break;
  474.  
  475.             case mmioFOURCC('J', 'U', 'N', 'K'):
  476.                 break;
  477.  
  478.         case mmioFOURCC('P', 'A', 'D', ' '):
  479.         break;
  480.  
  481.         case mmioFOURCC('c', 'u', 'e', ' '):
  482.         break;
  483.  
  484.     // copy chunks that are OK to copy
  485.  
  486.         case mmioFOURCC('p', 'l', 's', 't'):
  487.         // although without the 'cue' chunk, it doesn't make much sense
  488.                 riffCopyChunk(lpwc->hmmioSrc, lpwc->hmmioDst, &ck);
  489.         break;
  490.  
  491.         case mmioFOURCC('D', 'I', 'S', 'P'):
  492.                 riffCopyChunk(lpwc->hmmioSrc, lpwc->hmmioDst, &ck);
  493.         break;
  494.  
  495.         
  496.     // don't copy unknown chunks
  497.         
  498.             default:
  499.                 break;
  500.         }
  501.  
  502.         //
  503.         //  step up to prepare for next chunk..
  504.         //
  505.         mmioAscend(lpwc->hmmioSrc, &ck, 0);
  506.     }
  507.     //
  508.     // now write out possibly editted chunks...
  509.     //
  510.     if(riffWriteINFO(lpwc->hmmioDst, (glpwio->pInfo)))
  511.     {
  512.     goto wcb_Error;
  513.     }
  514.  
  515.  
  516.     //
  517.     // go back to beginning of data portion of WAVE chunk
  518.     //
  519.     if (mmioSeek(lpwc->hmmioSrc, ckSrcRIFF.dwDataOffset + sizeof(FOURCC),
  520.              SEEK_SET) == -1)
  521.         goto wcb_Error;
  522.  
  523.  
  524.     ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  525.     mmioDescend(lpwc->hmmioSrc, &ck, &ckSrcRIFF, MMIO_FINDCHUNK);
  526.  
  527.     //
  528.     //  now create the destination fmt, fact, and data chunks _in that order_
  529.     //
  530.     //
  531.     //
  532.     //  hmmio is now descended into the 'RIFF' chunk--create the format chunk
  533.     //  and write the format header into it
  534.     //
  535.     if (lpwc->lpwfxDst->wFormatTag == WAVE_FORMAT_PCM)
  536.         dw = sizeof(PCMWAVEFORMAT);
  537.     else
  538.         dw = sizeof(WAVEFORMATEX) + lpwc->lpwfxDst->cbSize;
  539.     lpwc->ckDst.ckid   = mmioFOURCC('f', 'm', 't', ' ');
  540.     lpwc->ckDst.cksize = dw;
  541.     if (mmioCreateChunk(lpwc->hmmioDst, &lpwc->ckDst, 0))
  542.         goto wcb_Error;
  543.  
  544.     if (mmioWrite(lpwc->hmmioDst, (HPSTR)lpwc->lpwfxDst, dw) != (LONG)dw)
  545.         goto wcb_Error;
  546.  
  547.     if (mmioAscend(lpwc->hmmioDst, &lpwc->ckDst, 0) != 0)
  548.         goto wcb_Error;
  549.  
  550.     //
  551.     //  create the 'fact' chunk (not necessary for PCM--but is nice to have)
  552.     //  since we are not writing any data to this file (yet), we set the
  553.     //  samples contained in the file to 0..
  554.     //
  555.     lpwc->ckDst.ckid   = mmioFOURCC('f', 'a', 'c', 't');
  556.     lpwc->ckDst.cksize = 0L;
  557.     if (mmioCreateChunk(lpwc->hmmioDst, &lpwc->ckDst, 0))
  558.         goto wcb_Error;
  559.  
  560.     if (mmioWrite(lpwc->hmmioDst, (HPSTR)&lpwc->dwSrcSamples, sizeof(DWORD)) != sizeof(DWORD))
  561.         goto wcb_Error;
  562.  
  563.     if (mmioAscend(lpwc->hmmioDst, &lpwc->ckDst, 0) != 0)
  564.         goto wcb_Error;
  565.  
  566.     //
  567.     //  create the data chunk AND STAY DESCENDED... for reasons that will
  568.     //  become apparent later..
  569.     //
  570.     lpwc->ckDst.ckid   = mmioFOURCC('d', 'a', 't', 'a');
  571.     lpwc->ckDst.cksize = 0L;
  572.     if (mmioCreateChunk(lpwc->hmmioDst, &lpwc->ckDst, 0))
  573.         goto wcb_Error;
  574.  
  575.     //
  576.     //  at this point, BOTH the src and dst files are sitting at the very
  577.     //  beginning of their data chunks--so we can READ from the source,
  578.     //  CONVERT the data, then WRITE it to the destination file...
  579.     //
  580.  
  581.     return (TRUE);
  582.  
  583.  
  584.     //
  585.     //
  586.     //
  587.     //
  588. wcb_Error:
  589.  
  590.     WaveConvEnd(hdlg, lpwc);
  591.     return (FALSE);
  592. } /* WaveConvBegin() */
  593.  
  594.  
  595. /** BOOL NEAR PASCAL WaveConvConvert(HWND hdlg, LPWAVECONVCB lpwc)
  596.  *
  597.  *  DESCRIPTION:
  598.  *      
  599.  *
  600.  *  ARGUMENTS:
  601.  *      (HWND hdlg, LPWAVECONVCB lpwc)
  602.  *
  603.  *  RETURN (BOOL NEAR PASCAL):
  604.  *
  605.  *
  606.  *  NOTES:
  607.  *
  608.  ** */
  609.  
  610. BOOL NEAR PASCAL WaveConvConvert(HWND hdlg, LPWAVECONVCB lpwc)
  611. {
  612.     char    ach[10];
  613.     DWORD   dw;
  614.     DWORD   dwCurrent;
  615.     WORD    w;
  616.     WORD    wCurPercent = (WORD)-1;
  617.  
  618.     for (dwCurrent = 0; dwCurrent < lpwc->dwSrcBytes; )
  619.     {
  620.         w = (WORD)((dwCurrent * 100) / lpwc->dwSrcBytes);
  621.         if (w != wCurPercent)
  622.         {
  623.             wCurPercent = w;
  624.             wsprintf(ach, "%u%%", wCurPercent);
  625.             SetDlgItemText(hdlg, IDD_TXT_STATUS, ach);
  626.         }
  627.  
  628.         AppDlgYield(hdlg);
  629.         if (gfCancelConvert)
  630.             goto wcc_Error;
  631.  
  632.         //
  633.         //
  634.         //
  635.         w = (WORD)min(lpwc->dwSrcReadSize, lpwc->dwSrcBytes - dwCurrent);
  636.         dw = mmioRead(lpwc->hmmioSrc, lpwc->hpSrc, w);
  637.         if (dw == 0L)
  638.             break;
  639.  
  640.         dwCurrent += dw;
  641.  
  642.         AppDlgYield(hdlg);
  643.         if (gfCancelConvert)
  644.             goto wcc_Error;
  645.  
  646.         //
  647.         //  convert data
  648.         //
  649.         dw = (* lpwc->fpConvert)(lpwc->lpwfxSrc, lpwc->hpSrc, 
  650.                                  lpwc->lpwfxDst, lpwc->hpDst, dw);
  651.  
  652.         AppDlgYield(hdlg);
  653.         if (gfCancelConvert)
  654.             goto wcc_Error;
  655.  
  656.         //
  657.         //
  658.         //
  659.         if (mmioWrite(lpwc->hmmioDst, lpwc->hpDst, dw) != (LONG)dw)
  660.             goto wcc_Error;
  661.     }
  662.  
  663.     EndConvert(hdlg, !gfCancelConvert, lpwc);
  664.     return (!gfCancelConvert);
  665.  
  666. wcc_Error:
  667.  
  668.     EndConvert(hdlg, FALSE, lpwc);
  669.     return (FALSE);
  670. } /* WaveConvConvert() */
  671.  
  672.  
  673.  
  674. static BOOL Cls_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  675. {
  676.     HFONT           hFont;
  677.     LPWAVECONVCB    lpwc;
  678.  
  679.     lpwc = (LPWAVECONVCB)lParam;
  680.  
  681.     hFont = GetStockFont(ANSI_FIXED_FONT);
  682.  
  683.     SetWindowFont(GetDlgItem(hwnd, IDD_TXT_INFILEPATH), hFont, FALSE);
  684.     SetWindowFont(GetDlgItem(hwnd, IDD_TXT_OUTFILEPATH), hFont, FALSE);
  685.     SetWindowFont(GetDlgItem(hwnd, IDD_TXT_STATUS), hFont, FALSE);
  686.  
  687.     SetDlgItemText(hwnd, IDD_TXT_INFILEPATH, lpwc->lpszFilePathSrc);
  688.     SetDlgItemText(hwnd, IDD_TXT_OUTFILEPATH, lpwc->lpszFilePathDst);
  689.  
  690.     BeginConvert(hwnd, (WAVECONVCB FAR*)lParam);
  691.     return (TRUE);
  692. }
  693.  
  694. static void Cls_OnConvertBegin(HWND hwnd, WAVECONVCB FAR* lpwc)
  695. {
  696.     gfCancelConvert = FALSE;
  697.     if (WaveConvBegin(hwnd, lpwc))
  698.     {
  699.         WaveConvConvert(hwnd, lpwc);
  700.     }
  701.     else
  702.     {
  703.         EndConvert(hwnd, FALSE, lpwc);
  704.     }
  705. }
  706.  
  707. static void Cls_OnConvertEnd(HWND hwnd, BOOL fCancel, WAVECONVCB FAR* lpwc)
  708. {
  709.     WaveConvEnd(hwnd, lpwc);
  710.     EndDialog(hwnd, fCancel);
  711. }
  712.  
  713. static void Cls_OnCommandConvert(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  714. {
  715.     if (id == IDCANCEL)
  716.         gfCancelConvert = TRUE;
  717. }
  718.  
  719. /** BOOL FAR PASCAL DlgProcConvert(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  720.  *
  721.  *  DESCRIPTION:
  722.  *      
  723.  *
  724.  *  ARGUMENTS:
  725.  *      (HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  726.  *
  727.  *  RETURN (BOOL FAR PASCAL):
  728.  *
  729.  *
  730.  *  NOTES:
  731.  *
  732.  ** */
  733.  
  734. BOOL FAR PASCAL DlgProcConvert(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  735. {
  736.     switch (uMsg)
  737.     {
  738.         case WM_INITDIALOG:
  739.             return (BOOL)(UINT)(DWORD)(LRESULT)HANDLE_WM_INITDIALOG(hdlg, wParam, lParam, Cls_OnInitDialog);
  740.  
  741.         case WM_CONVERT_BEGIN:
  742.             HANDLE_WM_CONVERT_BEGIN(hdlg, wParam, lParam, Cls_OnConvertBegin);
  743.             break;
  744.  
  745.         case WM_CONVERT_END:
  746.             HANDLE_WM_CONVERT_END(hdlg, wParam, lParam, Cls_OnConvertEnd);
  747.             break;
  748.  
  749.         case WM_COMMAND:
  750.             HANDLE_WM_COMMAND(hdlg, wParam, lParam, Cls_OnCommandConvert);
  751.             break;
  752.     }
  753.  
  754.     return (FALSE);
  755. } /* DlgProcConvert() */
  756.  
  757.  
  758. static void Cls_OnCommandAbout(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  759. {
  760.     if ((id == IDOK) || (id == IDCANCEL))
  761.         EndDialog(hwnd, (id == IDOK));
  762. }
  763.  
  764. /** BOOL FAR PASCAL DlgProcAbout(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  765.  *
  766.  *  DESCRIPTION:
  767.  *      
  768.  *
  769.  *  ARGUMENTS:
  770.  *      (HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  771.  *
  772.  *  RETURN (BOOL FAR PASCAL):
  773.  *
  774.  *
  775.  *  NOTES:
  776.  *
  777.  ** */
  778.  
  779. BOOL FAR PASCAL DlgProcAbout(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  780. {
  781.     switch (uMsg)
  782.     {
  783.         case WM_INITDIALOG:
  784.             return (TRUE);
  785.  
  786.         case WM_COMMAND:
  787.             HANDLE_WM_COMMAND(hdlg, wParam, lParam, Cls_OnCommandAbout);
  788.             break;
  789.     }
  790.  
  791.     return (FALSE);
  792. } /* DlgProcAbout() */
  793.  
  794.  
  795. /** void NEAR PASCAL WaveConvFileClose(void)
  796.  *
  797.  *  DESCRIPTION:
  798.  *      
  799.  *
  800.  *  ARGUMENTS:
  801.  *      (void)
  802.  *
  803.  *  RETURN (void NEAR PASCAL):
  804.  *
  805.  *
  806.  *  NOTES:
  807.  *
  808.  ** */
  809.  
  810. void NEAR PASCAL WaveConvFileClose(void)
  811. {
  812.     //
  813.     //  shut down any file we have open, etc.
  814.     //
  815.     if (glpwio)
  816.     {
  817.     wioFileClose(&glpwio,0);
  818.         glpwfx = NULL;
  819.     glpwio=NULL;
  820.     }
  821.  
  822.     lstrcpy(gszWaveFilePath, gszNone);
  823.     lstrcpy(gszWaveFormat, gszUnknown);
  824. } /* WaveConvFileClose() */
  825.  
  826.  
  827. /** BOOL NEAR PASCAL WaveConvFileOpen(HWND hwnd)
  828.  *
  829.  *  DESCRIPTION:
  830.  *      
  831.  *
  832.  *  ARGUMENTS:
  833.  *      (HWND hwnd)
  834.  *
  835.  *  RETURN (BOOL NEAR PASCAL):
  836.  *
  837.  *
  838.  *  NOTES:
  839.  *
  840.  ** */
  841.  
  842. BOOL NEAR PASCAL WaveConvFileOpen(HWND hwnd, LPSTR lpszFilePath)
  843. {
  844.  
  845.     LRESULT         lr;
  846.     LPWAVEFORMATEX  lpwfx;
  847.  
  848.     //
  849.     // close anything that is open
  850.     //
  851.     WaveConvFileClose();
  852.     
  853.     //
  854.     //  we have a valid file name, now attempt to open the file and see
  855.     //  if we can deal with it... currently, this means it must either
  856.     //  be a valid PCM or ADPCM file...
  857.     //
  858.     //  so, first get the wave header (just the common info...) then
  859.     //  verify that it is way-q-zomo...
  860.     //
  861.     lr = wioFileOpen(&glpwio, lpszFilePath, 0L);
  862.     if (lr)
  863.     {
  864.         DPF("WaveConvFileOpen: wioFileOpen failed=%lu", lr);
  865.         AppErrorMsg(hwnd, "%ls is not a valid wave file.", lpszFilePath);
  866.         return (FALSE);
  867.     }
  868.  
  869.     //
  870.     //  name the thing if we know what type it is
  871.     //
  872.     lpwfx = &glpwio->wfx;
  873.     wsupGetFormatName(lpwfx, gszWaveFormat);
  874.  
  875.     glpwfx = lpwfx;
  876.  
  877.     //
  878.     //
  879.     //
  880.     lstrcpy(gszWaveFilePath, lpszFilePath);
  881.  
  882.     //
  883.     //  something changed...
  884.     //
  885.     return (TRUE);
  886. } /* WaveConvFileOpen() */
  887.  
  888.  
  889. /** BOOL NEAR PASCAL WaveConvGetNewFile(HWND hwnd)
  890.  *
  891.  *  DESCRIPTION:
  892.  *      
  893.  *
  894.  *  ARGUMENTS:
  895.  *      (HWND hwnd)
  896.  *
  897.  *  RETURN (BOOL NEAR PASCAL):
  898.  *
  899.  *
  900.  *  NOTES:
  901.  *
  902.  ** */
  903.  
  904. BOOL NEAR PASCAL WaveConvGetNewFile(HWND hwnd)
  905. {
  906.     BOOL    f;
  907.     char    szFilePath[MAX_FILE_PATH_LEN];
  908.  
  909.     //
  910.     //  toss up a commdlg file open thing to get a .wav file to work with
  911.     //
  912.     f = AppGetFileName(hwnd, szFilePath, NULL, AGFN_FLAG_OPEN);
  913.     if (!f)
  914.         return (FALSE);
  915.  
  916.     //
  917.     //  attempt to open the wave file..
  918.     //
  919.     WaveConvFileOpen(hwnd, szFilePath);
  920.    
  921.     //
  922.     //  always say that something changed if a file was selected (regardless
  923.     //  of whether it was a valid wave file or not). the reason for this is
  924.     //  to make sure that display gets updated...
  925.     //
  926.     return (TRUE);
  927. } /* WaveConvGetNewFile() */
  928.  
  929.  
  930. /** BOOL NEAR PASCAL WaveConvSaveFileAs(HWND hwnd)
  931.  *
  932.  *  DESCRIPTION:
  933.  *      
  934.  *
  935.  *  ARGUMENTS:
  936.  *      (HWND hwnd)
  937.  *
  938.  *  RETURN (BOOL NEAR PASCAL):
  939.  *
  940.  *
  941.  *  NOTES:
  942.  *
  943.  ** */
  944.  
  945. BOOL NEAR PASCAL WaveConvSaveFileAs(HWND hwnd)
  946. {
  947.     CONVERTPROC     fpConvert;
  948.     BOOL            f;
  949.     PSTR            psz;
  950.     LPWAVEFORMATEX  lpwfxDst;
  951.     WORD            wHdrSize;
  952.  
  953.  
  954.     //
  955.     //  get the output file name... 
  956.     //
  957.     f = AppGetFileName(hwnd, gszSaveFilePath, NULL, AGFN_FLAG_SAVE);
  958.     if (!f)
  959.         return (FALSE);
  960.  
  961.     //
  962.     //
  963.     //
  964.     psz       = NULL;
  965.     wHdrSize  = 0;
  966.     fpConvert = NULL;
  967.     switch (glpwfx->wFormatTag)
  968.     {
  969.         case WAVE_FORMAT_PCM:
  970.             if (!pcmIsValidFormat(glpwfx))
  971.             {
  972.                 psz = "This PCM wave file is not valid for conversion!";
  973.                 break;
  974.             }
  975.  
  976.             //
  977.             //  !!! hack hack hack !!! should have some way of 'determining'
  978.             //  wave header size rather than hardcoding...
  979.             //
  980.             wHdrSize  = sizeof(WAVEFORMATEX) + 32;
  981.             fpConvert = (CONVERTPROC)msadpcmEncode4Bit;
  982.             break;
  983.  
  984.         case WAVE_FORMAT_ADPCM:
  985.             if (!msadpcmIsValidFormat(glpwfx))
  986.             {
  987.                 psz = "This ADPCM wave file is not valid for conversion!";
  988.                 break;
  989.             }
  990.  
  991.             wHdrSize  = sizeof(WAVEFORMATEX);
  992.             fpConvert = (CONVERTPROC)msadpcmDecode4Bit;
  993.             break;
  994.  
  995.         default:
  996.             psz = "This wave converter application does not know how to convert current format!";
  997.             break;
  998.     }
  999.  
  1000.  
  1001.     //
  1002.     //  blast out an error msg if appropriate and fail if we should
  1003.     //  
  1004.     if (psz)
  1005.     {
  1006.         AppErrorMsg(hwnd, psz);
  1007.         return (FALSE);
  1008.     }
  1009.  
  1010.     //
  1011.     //  
  1012.     //
  1013.     //
  1014.     //
  1015.     lpwfxDst = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, wHdrSize);
  1016.     if (!lpwfxDst)
  1017.     {
  1018.         AppErrorMsg(hwnd, "Could not allocate destination conversion header!");
  1019.         return (FALSE);
  1020.     }
  1021.  
  1022.     //
  1023.     //  build the destination format header and then call the conversion
  1024.     //  dialog box...
  1025.     //
  1026.     f = msadpcmBuildFormatHeader(glpwfx, lpwfxDst);
  1027.     if (f)
  1028.     {
  1029.         _fmemset(&gwc, 0, sizeof(gwc));
  1030.  
  1031.         gwc.dwSrcSamples    = glpwio->dwDataSamples;
  1032.         gwc.lpszFilePathSrc = gszWaveFilePath;
  1033.         gwc.lpwfxSrc        = glpwfx;
  1034.         gwc.lpszFilePathDst = gszSaveFilePath;
  1035.         gwc.lpwfxDst        = lpwfxDst;
  1036.         gwc.fpConvert       = fpConvert;
  1037.  
  1038.         gwc.dwSrcBytes      = glpwio->dwDataBytes;
  1039.  
  1040.         //
  1041.         //
  1042.         //
  1043.         if (lpwfxDst->wFormatTag == WAVE_FORMAT_PCM)
  1044.         {
  1045.             gwc.dwSrcReadSize = glpwfx->nBlockAlign;
  1046.             gwc.dwDstBufSize  = ((LPADPCMWAVEFORMAT)glpwfx)->wSamplesPerBlock * lpwfxDst->nBlockAlign;
  1047.         }
  1048.         else
  1049.         {
  1050.             gwc.dwSrcReadSize = ((LPADPCMWAVEFORMAT)lpwfxDst)->wSamplesPerBlock * glpwfx->nBlockAlign;
  1051.             gwc.dwDstBufSize  = lpwfxDst->nBlockAlign;
  1052.         }
  1053.  
  1054.         f = AppDialogBox(hwnd, DLG_CONVERT, DlgProcConvert, (LPARAM)(LPVOID)&gwc);
  1055.         if (f)
  1056.             psz = "Conversion completed successfully!";
  1057.         else
  1058.             psz = "Conversion aborted--destination file is corrupt!";
  1059.  
  1060.         MessageBox(hwnd, psz, gszAppName, MB_OK);
  1061.     }
  1062.     else
  1063.     {
  1064.         AppErrorMsg(hwnd, "There is something invalid/corrupt in the source header!");
  1065.     }
  1066.  
  1067.     //
  1068.     //  free the destination format header if it was alloc'd
  1069.     //
  1070.     if (lpwfxDst)
  1071.         GlobalFreePtr(lpwfxDst);
  1072.  
  1073.     return (f);
  1074. } /* WaveConvSaveFileAs() */
  1075.  
  1076. void NEAR PASCAL waveconvDumpWaveFormat(HDC hdc, LPWAVEFORMATEX lpwfx, WORD x, WORD y, WORD nFontHeight)
  1077. {
  1078.     WORD    w;
  1079.     char    ach[128 + 64];
  1080.     WORD nLength;
  1081.     
  1082.     nLength = wsprintf(ach, "          Wave Format: [%u], %ls",
  1083.                         glpwfx->wFormatTag, (LPSTR)gszWaveFormat);
  1084.     TextOut(hdc, x, y, ach, nLength);  y += nFontHeight;
  1085.  
  1086.     nLength = wsprintf(ach, "             Channels: %u", glpwfx->nChannels);
  1087.     TextOut(hdc, x, y, ach, nLength);  y += nFontHeight;
  1088.  
  1089.     nLength = wsprintf(ach, "   Samples Per Second: %lu", glpwfx->nSamplesPerSec);
  1090.     TextOut(hdc, x, y, ach, nLength);  y += nFontHeight;
  1091.  
  1092.     nLength = wsprintf(ach, " Avg Bytes Per Second: %lu", glpwfx->nAvgBytesPerSec);
  1093.     TextOut(hdc, x, y, ach, nLength);  y += nFontHeight;
  1094.  
  1095.     nLength = wsprintf(ach, "      Block Alignment: %u", glpwfx->nBlockAlign);
  1096.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1097.  
  1098.     nLength = wsprintf(ach, "      Bits Per Sample: %u", glpwfx->wBitsPerSample);
  1099.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1100.  
  1101.     nLength = wsprintf(ach, "   Extra Header Bytes: %u", glpwfx->cbSize);
  1102.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1103.  
  1104.     y += 5;
  1105.  
  1106.     //
  1107.     //  more silly hardcoded stuff to show info about ADPCM file
  1108.     //
  1109.     if (glpwfx->wFormatTag == WAVE_FORMAT_ADPCM)
  1110.     {
  1111.         LPADPCMWAVEFORMAT   lpwfxA;
  1112.  
  1113.         lpwfxA = (LPADPCMWAVEFORMAT)glpwfx;
  1114.  
  1115.         nLength = wsprintf(ach, "    Samples Per Block: %u", lpwfxA->wSamplesPerBlock);
  1116.         TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1117.  
  1118.         nLength = wsprintf(ach, "    Coefficient Pairs: %u", lpwfxA->wNumCoef);
  1119.         TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1120.  
  1121.         for (w = 0; w < lpwfxA->wNumCoef; w++)
  1122.         {
  1123.             nLength = wsprintf(ach, "              Pair #%u: (%4d,%4d)", w + 1,
  1124.                             lpwfxA->aCoef[w].iCoef1, lpwfxA->aCoef[w].iCoef2);
  1125.             TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1126.         }
  1127.     }
  1128.     
  1129.     y += 5;
  1130.  
  1131.     //
  1132.     //  some other stats
  1133.     //
  1134.     nLength = wsprintf(ach, "     Total Data Bytes: %lu", glpwio->dwDataBytes);
  1135.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1136.  
  1137.     nLength = wsprintf(ach, "   Total Data Samples: %lu", glpwio->dwDataSamples);
  1138.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1139. }
  1140.  
  1141. /** void NEAR PASCAL AppPaint(HWND hwnd, HDC hdc)
  1142.  *
  1143.  *  DESCRIPTION:
  1144.  *      
  1145.  *
  1146.  *  ARGUMENTS:
  1147.  *      (HWND hwnd, HDC hdc)
  1148.  *
  1149.  *  RETURN (void NEAR PASCAL):
  1150.  *
  1151.  *
  1152.  *  NOTES:
  1153.  *
  1154.  ** */
  1155.  
  1156. void NEAR PASCAL AppPaint(HWND hwnd, HDC hdc)
  1157. {
  1158.     static  int nFontHeight = 0;
  1159.     char    ach[128 + 64];
  1160.     int     nLength;
  1161.     int     y;
  1162.  
  1163.     //
  1164.     //  this is terribly inefficient--but i don't care right now... this
  1165.     //  whole paint routine is poorly written!
  1166.     //
  1167.     SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1168.     SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1169.     SelectFont(hdc, GetStockFont(ANSI_FIXED_FONT));
  1170.  
  1171.     if (nFontHeight == 0)
  1172.     {
  1173.         TEXTMETRIC  tm;
  1174.         GetTextMetrics(hdc, &tm);
  1175.         nFontHeight = (int)tm.tmHeight;
  1176.     }
  1177.  
  1178.     y = 5;
  1179.     
  1180.     nLength = wsprintf(ach, "       Wave File Path: %ls", (LPSTR)gszWaveFilePath);
  1181.     TextOut(hdc, 5, y, ach, nLength);  y += nFontHeight;
  1182.  
  1183.     y += 5;
  1184.  
  1185.     //
  1186.     //  if nothing more to display, then don't 
  1187.     //
  1188.     if (!glpwfx)
  1189.         return;
  1190.  
  1191.     waveconvDumpWaveFormat(hdc, glpwfx, 5, y, nFontHeight);
  1192.     
  1193.  
  1194. } /* AppPaint() */
  1195.  
  1196.  
  1197. /** LRESULT NEAR PASCAL AppCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1198.  *
  1199.  *  DESCRIPTION:
  1200.  *      
  1201.  *
  1202.  *  ARGUMENTS:
  1203.  *      (HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1204.  *
  1205.  *  RETURN (LRESULT NEAR PASCAL):
  1206.  *
  1207.  *
  1208.  *  NOTES:
  1209.  *
  1210.  ** */
  1211.  
  1212. LRESULT NEAR PASCAL AppCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1213. {
  1214.     BOOL    f;
  1215.     LRESULT lr;
  1216.  
  1217.     switch (id)
  1218.     {
  1219.     case IDM_PLAY:
  1220.         if(wioIsPlaying(glpwio))
  1221.         wioStopWave(glpwio);
  1222.         else
  1223.         {
  1224.         lr=wioPlayWave(hwnd, glpwio, gszWaveFilePath, 0);
  1225.         switch(lr)
  1226.         {
  1227.             case WIOERR_NOERROR:
  1228.             // everything OK
  1229.             break;
  1230.             case WIOERR_ALLOCATED:
  1231.             AppErrorMsg(hwnd, lpplayerr, (LPCSTR)"Output device alread allocated");
  1232.             break;
  1233.         
  1234.             case WIOERR_NOTSUPPORTED:
  1235.             AppErrorMsg(hwnd, lpplayerr, (LPCSTR)"No available device supports this format");
  1236.             break;
  1237.             default:
  1238.             AppErrorMsg(hwnd, lpplayerr, (LPCSTR)"Unknown Error");
  1239.         }
  1240.         }
  1241.         break;
  1242.         
  1243.     case IDM_DISP:
  1244.         break;
  1245.  
  1246.     case IDM_FORMAT:
  1247.         break;
  1248.         
  1249.     case IDM_STEREO:
  1250.         break;
  1251.         
  1252.     case IDM_MONO:
  1253.         break;
  1254.         
  1255.     case IDM_SAMPLE:
  1256.         break;
  1257.         
  1258.     case IDM_INFO:
  1259.         riffEditINFO(hwnd, glpwio->pInfo, ghInstance);
  1260.         break;
  1261.         
  1262.         case IDM_FILE_OPEN:
  1263.             //
  1264.             //  try to get a new wave file--if something changes, then update
  1265.             //  the display...
  1266.             //
  1267.             f = WaveConvGetNewFile(hwnd);
  1268.             if (f)
  1269.             {
  1270.                 InvalidateRect(hwnd, NULL, TRUE);
  1271.                 UpdateWindow(hwnd);
  1272.             }
  1273.             break;
  1274.  
  1275.         case IDM_FILE_SAVEAS:
  1276.             if (glpwio)
  1277.             {
  1278.                 WaveConvSaveFileAs(hwnd);
  1279.             }
  1280.             break;
  1281.  
  1282.         case IDM_FILE_ABOUT:
  1283.             AppDialogBox(hwnd, ABOUTBOX, DlgProcAbout, 0L);
  1284.             break;
  1285.  
  1286.         case IDM_FILE_EXIT:
  1287.             FORWARD_WM_CLOSE(hwnd, SendMessage);
  1288.             break;
  1289.     }
  1290.  
  1291.     return (0L);
  1292. } /* AppCommand() */
  1293.  
  1294.  
  1295. /** void NEAR PASCAL AppInitMenu(HWND hwnd, HMENU hMenu)
  1296.  *
  1297.  *  DESCRIPTION:
  1298.  *      
  1299.  *
  1300.  *  ARGUMENTS:
  1301.  *      (HWND hwnd, HMENU hMenu)
  1302.  *
  1303.  *  RETURN (void NEAR PASCAL):
  1304.  *
  1305.  *
  1306.  *  NOTES:
  1307.  *
  1308.  ** */
  1309.  
  1310. void NEAR PASCAL AppInitMenu(HWND hwnd, HMENU hMenu)
  1311. {
  1312.     UINT    mf;
  1313.  
  1314.     mf = glpwio ? MF_ENABLED : MF_GRAYED;
  1315.     EnableMenuItem(hMenu, IDM_FILE_SAVEAS, mf);
  1316.     EnableMenuItem(hMenu, IDM_INFO, mf);
  1317.     EnableMenuItem(hMenu, IDM_DISP, mf);
  1318.  
  1319.     ModifyMenu(hMenu,IDM_PLAY, MF_BYCOMMAND | MF_STRING | mf, IDM_PLAY, glpwio && wioIsPlaying(glpwio) ? "&Stop" : "&Play");
  1320.     
  1321.  
  1322. } /* AppInitMenu() */
  1323.  
  1324.  
  1325. /** void NEAR PASCAL AppAcceptDroppedFiles(HWND hwnd, HDROP hDrop)
  1326.  *
  1327.  *  DESCRIPTION:
  1328.  *      
  1329.  *
  1330.  *  ARGUMENTS:
  1331.  *      (HWND hwnd, HDROP hDrop)
  1332.  *
  1333.  *  RETURN (void NEAR PASCAL):
  1334.  *
  1335.  *
  1336.  *  NOTES:
  1337.  *
  1338.  ** */
  1339.  
  1340. void NEAR PASCAL AppAcceptDroppedFiles(HWND hwnd, HDROP hDrop)
  1341. {
  1342.     char    szFilePath[MAX_FILE_PATH_LEN];
  1343.     WORD    wNumFiles;
  1344.     WORD    w;
  1345.     BOOL    f;
  1346.     int     i;
  1347.  
  1348.     //
  1349.     //  get number of files dropped on our window
  1350.     //
  1351.     wNumFiles = DragQueryFile(hDrop, (UINT)-1, NULL, 0);
  1352.  
  1353.     //
  1354.     //  step through each file and stop on the one the user wants or 
  1355.     //  the last file (whichever comes first).
  1356.     //
  1357.     for (w = 0; w < wNumFiles; w++)
  1358.     {
  1359.         // 
  1360.         //  get the next file name and try to open it--if not a valid wave
  1361.         //  file, then skip to the next one (if there is one).
  1362.         //
  1363.         DragQueryFile(hDrop, w, (LPSTR)szFilePath, sizeof(szFilePath));
  1364.  
  1365.         f = WaveConvFileOpen(hwnd, szFilePath);
  1366.  
  1367.         //
  1368.         //  force update to display (even if file is not valid)
  1369.         //
  1370.         InvalidateRect(hwnd, NULL, TRUE);
  1371.         UpdateWindow(hwnd);
  1372.  
  1373.         //
  1374.         //  if this is NOT the last file in the list of files that are
  1375.         //  being dropped on us, then bring up a box asking if we should
  1376.         //  continue or stop where we are..
  1377.         //
  1378.         if (f && (w != (wNumFiles - 1)))
  1379.         {
  1380.             i = MessageBox(hwnd, "Continue?", gszAppName,
  1381.                         MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL);
  1382.             if (i == IDNO)
  1383.                 break;
  1384.         }
  1385.     }
  1386.  
  1387.     //
  1388.     //  tell the shell to release the memory it allocated for beaming
  1389.     //  the file name(s) over to us...
  1390.     //
  1391.     DragFinish(hDrop);
  1392. } /* AppAcceptDroppedFiles() */
  1393.  
  1394.  
  1395. static void Cls_OnPaint(HWND hwnd)
  1396. {
  1397.     PAINTSTRUCT ps;
  1398.  
  1399.     BeginPaint(hwnd, &ps);
  1400.     AppPaint(hwnd, ps.hdc);
  1401.     EndPaint(hwnd, &ps);
  1402. }
  1403.  
  1404. /** LRESULT FAR PASCAL WndProcApp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1405.  *
  1406.  *  DESCRIPTION:
  1407.  *      
  1408.  *
  1409.  *  ARGUMENTS:
  1410.  *      (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1411.  *
  1412.  *  RETURN (LRESULT FAR PASCAL):
  1413.  *
  1414.  *
  1415.  *  NOTES:
  1416.  *
  1417.  ** */
  1418.  
  1419. LRESULT FAR PASCAL WndProcApp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1420. {
  1421.     switch (uMsg) 
  1422.     {
  1423.         case WM_DESTROY:
  1424.             PostQuitMessage(0);
  1425.             break;
  1426.  
  1427.         case WM_INITMENU:
  1428.             HANDLE_WM_INITMENU(hwnd, wParam, lParam, AppInitMenu);
  1429.             break;
  1430.  
  1431.         case WM_COMMAND:
  1432.             return HANDLE_WM_COMMAND(hwnd, wParam, lParam, AppCommand);
  1433.  
  1434.         case WM_CLOSE:
  1435.             HANDLE_WM_CLOSE(hwnd, wParam, lParam, DestroyWindow);
  1436.             break;
  1437.  
  1438.         case WM_PAINT:
  1439.             HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);
  1440.             break;
  1441.  
  1442.         case WM_DROPFILES:
  1443.             HANDLE_WM_DROPFILES(hwnd, wParam, lParam, AppAcceptDroppedFiles);
  1444.             break;
  1445.         
  1446.         case MM_WOM_DONE:
  1447.         wioWaveOutDone(glpwio, (LPWAVEHDR) lParam);
  1448.         return TRUE;
  1449.  
  1450.  
  1451.         default:
  1452.             return (DefWindowProc(hwnd, uMsg, wParam, lParam));
  1453.     }
  1454.  
  1455.     return (0L);
  1456. } /* WndProcApp() */
  1457.  
  1458.  
  1459. /** BOOL NEAR PASCAL AppInit(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  1460.  *
  1461.  *  DESCRIPTION:
  1462.  *      
  1463.  *
  1464.  *  ARGUMENTS:
  1465.  *      (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  1466.  *
  1467.  *  RETURN (BOOL NEAR PASCAL):
  1468.  *
  1469.  *
  1470.  *  NOTES:
  1471.  *
  1472.  ** */
  1473.  
  1474. BOOL NEAR PASCAL AppInit(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  1475. {
  1476.     WNDCLASS    wc;
  1477.  
  1478.     ghInstance = hInstance;
  1479.  
  1480.     if (!hPrevInstance) 
  1481.     {
  1482.         wc.style            = CS_HREDRAW | CS_VREDRAW;
  1483.         wc.lpfnWndProc      = WndProcApp;
  1484.         wc.cbClsExtra       = 0;
  1485.         wc.cbWndExtra       = 0;
  1486.         wc.hInstance        = hInstance;
  1487.         wc.hIcon            = LoadIcon(hInstance, ICON_APP);
  1488.         wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  1489.         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
  1490.         wc.lpszMenuName     = MENU_APP;
  1491.         wc.lpszClassName    = gszAppName;
  1492.  
  1493.         if (!RegisterClass(&wc))
  1494.             return (FALSE);
  1495.     }
  1496.  
  1497.     //
  1498.     //  init wave file vars, etc..
  1499.     //
  1500.     WaveConvFileClose();
  1501.  
  1502.     //
  1503.     //  open the app's window
  1504.     //
  1505.     ghwnd = CreateWindow(gszAppName, gszAppName, WS_OVERLAPPEDWINDOW,
  1506.                           CW_USEDEFAULT, CW_USEDEFAULT,
  1507.                           APP_WINDOW_WIDTH, APP_WINDOW_HEIGHT,
  1508.                           NULL, NULL, hInstance, NULL);             
  1509.  
  1510.     if (!ghwnd)
  1511.         return (FALSE);
  1512.  
  1513.     //
  1514.     //  register the app's window for drag-drop messages from winfile
  1515.     //
  1516.     DragAcceptFiles(ghwnd, TRUE);
  1517.  
  1518.     ShowWindow(ghwnd, nCmdShow);
  1519. //  UpdateWindow(ghwnd);
  1520.  
  1521.     return (TRUE);
  1522. } /* AppInit() */
  1523.  
  1524.  
  1525. /** void NEAR PASCAL AppExit(void)
  1526.  *
  1527.  *  DESCRIPTION:
  1528.  *      
  1529.  *
  1530.  *  ARGUMENTS:
  1531.  *      (void)
  1532.  *
  1533.  *  RETURN (void NEAR PASCAL):
  1534.  *
  1535.  *
  1536.  *  NOTES:
  1537.  *
  1538.  ** */
  1539.  
  1540. void NEAR PASCAL AppExit(void)
  1541. {
  1542.     //
  1543.     //  shut down any file we have open, etc.
  1544.     //
  1545.     WaveConvFileClose();
  1546.  
  1547. } /* AppExit() */
  1548.  
  1549.  
  1550. /** int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  1551.  *
  1552.  *  DESCRIPTION:
  1553.  *      
  1554.  *
  1555.  *  ARGUMENTS:
  1556.  *      (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  1557.  *
  1558.  *  RETURN (int PASCAL):
  1559.  *
  1560.  *
  1561.  *  NOTES:
  1562.  *
  1563.  ** */
  1564.  
  1565. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  1566. {
  1567.     MSG     msg;
  1568.  
  1569.     //
  1570.     //  init some stuff, create window, etc..
  1571.     //
  1572.     if (AppInit(hInstance, hPrevInstance, lpszCmdLine, nCmdShow))
  1573.     {
  1574.         //
  1575.         //  dispatch messages
  1576.         //
  1577.         while (GetMessage(&msg, NULL, 0, 0))
  1578.         {
  1579.             TranslateMessage(&msg);
  1580.             DispatchMessage(&msg);
  1581.         }
  1582.     }
  1583.  
  1584.     //
  1585.     //  shut things down, clean up, etc.
  1586.     //
  1587.     AppExit();
  1588.  
  1589.     return (msg.wParam);
  1590. } /* WinMain() */
  1591.  
  1592.  
  1593. /*********************** BEGIN: DEBUGGING ANNEX ****************************/
  1594.  
  1595. #ifdef DEBUG
  1596.  
  1597. void FAR cdecl dprintf(LPSTR szFormat, ...)
  1598. {
  1599. //  extern FAR PASCAL OutputDebugStr(LPSTR);
  1600.     char ach[512];
  1601.     int  s,d;
  1602.  
  1603.     s = wvsprintf(ach,szFormat,(LPSTR)(&szFormat+1));
  1604. #if 1
  1605.     lstrcat(ach,"\n");
  1606.     s++;
  1607. #endif
  1608.     for (d=sizeof(ach)-1; s>=0; s--)
  1609.     {
  1610.         if ((ach[d--] = ach[s]) == '\n')
  1611.             ach[d--] = '\r';
  1612.     }
  1613.  
  1614.     OutputDebugStr("WAVECONV: ");
  1615.     OutputDebugStr(ach+d+1);
  1616. }
  1617.  
  1618. #endif
  1619.  
  1620. /************************ END: DEBUGGING ANNEX *****************************/
  1621.  
  1622.  
  1623. /** EOF: waveconv.c **/
  1624.