home *** CD-ROM | disk | FTP | other *** search
/ The Best of Windows 95.com 1996 September / WIN95_09964.iso / sound / mpw32-5s.zip / MP2WIN.CPP < prev    next >
C/C++ Source or Header  |  1996-07-31  |  38KB  |  1,449 lines

  1. #define STRICT
  2. #define WIN32_LEAN_AND_MEAN
  3. #define NOMCX
  4. #define NOIME
  5. // #define NOGDI
  6. // #define NOUSER
  7. #define NOSOUND
  8. #define NOCOMM
  9. #define NODRIVERS
  10. #define OEMRESOURCE
  11. #define NONLS
  12. #define NOSERVICE
  13. #define NOKANJI
  14. #define NOMINMAX
  15. #define NOLOGERROR
  16. #define NOPROFILER
  17. #define NOMEMMGR
  18. #define NOLFILEIO
  19. #define NOOPENFILE
  20. //#define NORESOURCE
  21. #define NOATOM
  22. #define NOLANGUAGE
  23. //#define NOLSTRING
  24. #define NODBCS
  25. #define NOKEYBOARDINFO
  26. #define NOGDICAPMASKS
  27. #define NOCOLOR
  28. #define NOGDIOBJ
  29. #define NODRAWTEXT
  30. #define NOTEXTMETRIC
  31. #define NOSCALABLEFONT
  32. //#define NOBITMAP
  33. #define NORASTEROPS
  34. #define NOMETAFILE
  35. #define NOSYSMETRICS
  36. #define NOSYSTEMPARAMSINFO
  37. // #define NOMSG
  38. //#define NOWINSTYLES
  39. #define NOWINOFFSETS
  40. #define NOSHOWWINDOW
  41. #define NODEFERWINDOWPOS
  42. #define NOVIRTUALKEYCODES
  43. #define NOKEYSTATES
  44. #define NOWH
  45. //#define NOMENUS
  46. //#define NOSCROLL
  47. #define NOCLIPBOARD
  48. //#define NOICONS
  49. //#define NOMB
  50. #define NOSYSCOMMANDS
  51. #define NOMDI
  52. //#define NOCTLMGR
  53. //#define NOWINMESSAGES
  54. #define NOHELP
  55. //#define _WINUSER_
  56. #define __oleidl_h__
  57. #define _OLE2_H_
  58. #include <windows.h>
  59. #include <mmsystem.h>
  60. #include "commctrl.h"
  61. #include <commdlg.h>
  62. #include <stdlib.h>
  63.  
  64. #include "crc.h"
  65. #include "ibitstr.h"
  66. #include "header.h"
  67. #include "mp2win.h"
  68. #include "args.h"
  69. #include <fstream.h>
  70. #include "subband.h"
  71.  
  72. #define _export
  73. #define GET_WM_COMMAND_ID(wp, lp)    LOWORD(wp)
  74. #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
  75. #define GET_WM_COMMAND_CMD(wp, lp)     HIWORD(wp)
  76.  
  77. /* Interface for maplay written by Jeff Tsay. E-mail address:
  78.     ctsay@pasteur.eecs.berkeley.edu. Basic sound file player with
  79.     file open, command line capability, pause, stop, and MPEG
  80.     properties. Also added play list and seeking functionality. Uses
  81.     threads, so will NOT work on Win32s!    */
  82.  
  83. /* Adapted from the Sounder sample application distributed on the
  84.     Borland C++ CD */
  85.  
  86. // Argument containers
  87. DWORD maplay(MPEG_Args *);
  88. DWORD mciplay(MCI_Args *);
  89.  
  90. // data initialized by first instance
  91. typedef struct tagSETUPDATA
  92.   {
  93.      char   szAppName[20]; // name of application
  94.   } SETUPDATA;
  95.  
  96. SETUPDATA SetUpData;
  97.  
  98. // Data that can be referenced throughout the
  99. // program but not passed to other instances
  100.  
  101. char        szName[256];    // Name of sound file
  102. char     FileTitle[256];
  103. char         TitleText[64];
  104. char     command[384];   // MCI command string
  105. char         scratch[64];
  106. char     Buffer[1024];         // MCI response string
  107. char     *PlayList[256];
  108.  
  109. OPENFILENAME ofnTemp;
  110. LPSTR szTemp = "MPEG Audio Files (*.mp*)\0*.mp*\0WAV Files \
  111. (*.wav)\0*.wav\0MIDI Files \ (*.mid)\0*.mid\0Playlists (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
  112.  
  113. int Cur_Index;
  114. int Max_Index;
  115.  
  116. int scroll_range=0;
  117. // int predecode=0;        // not implemented yet
  118.  
  119. BOOL ListMode = FALSE;
  120. BOOL MPEG = FALSE;
  121. BOOL Repeat = FALSE;
  122. BOOL CMDLINE = FALSE;
  123. BOOL paused = FALSE;
  124. BOOL can_play = FALSE;
  125. BOOL can_pause = FALSE;
  126. BOOL can_stop = FALSE;
  127. BOOL playing = FALSE;
  128. BOOL scrolling = FALSE;
  129. enum e_channels mode=both;
  130.  
  131. HWAVEOUT *phwo=new HWAVEOUT;
  132. HANDLE MPEG_Thread=NULL;
  133. HANDLE MCI_Thread=NULL;
  134.  
  135. MPEG_Args *maplay_args=new MPEG_Args();
  136. MCI_Args *mci_args = new MCI_Args();
  137. Args* args;
  138.  
  139. DWORD dwThreadId;
  140.  
  141. HINSTANCE    hInst;      // hInstance of application
  142. HWND      hWnd;          // hWnd of main window
  143.  
  144. // Buttons
  145. HWND openbut, playbut, pausebut, stopbut, aboutbut;
  146. HWND rewbut, ffbut, prevbut, repbut, nextbut;
  147.  
  148. // Track bar
  149. int line_size;
  150. HWND tracker;
  151.  
  152. // Status bar
  153. int panes[4]= {54, 200, 244, -1};
  154. char playlist_filename[64];
  155. HWND status_bar;
  156.  
  157. // Menu
  158. HMENU mainmenu;
  159.  
  160. HDC hdc;
  161. DRAWITEMSTRUCT *dis;
  162.  
  163. // Function prototypes
  164.  
  165. int      PASCAL        WinMain(HINSTANCE,HINSTANCE,LPSTR,int);
  166. void                   InitSound(HINSTANCE,HINSTANCE,LPSTR,int);
  167. void                   InitSoundFirst(HINSTANCE);
  168. void                   InitSoundEvery(HINSTANCE,int);
  169.  
  170. // Helper procedures
  171. BOOL AppFileOpen();
  172. void clear_sound();
  173. void ok_play();
  174. void no_play();
  175. void no_stop();
  176. BOOL reinit_MPEG();
  177. BOOL reinit_MCI();
  178. BOOL WaveP(LPSTR);
  179. BOOL ListP(LPSTR);
  180. LPSTR Proper_Filename(LPSTR s);
  181. void DisplayName(LPSTR);
  182. BOOL MPEG_play();
  183. BOOL MCI_play();
  184. BOOL Get_File_List(LPSTR);
  185. BOOL File_Init();
  186. void Next_Song();
  187. void Init_List();
  188. void no_list();
  189. char *time_string(int ms, char *dest);
  190. void update_timewin(int num);
  191.  
  192. // Menu procedures
  193. void file_open();
  194. void audio_play();
  195. void audio_pause();
  196. void audio_stop();
  197. void audio_properties();
  198. void gotop_List(int n);
  199. void about();
  200. void leave();
  201.  
  202. // Procedures for options dialog box
  203. void leave_options(HWND hDlg);
  204.  
  205. LRESULT APIENTRY SounderWndProc(HWND,UINT,WPARAM,LPARAM);
  206. BOOL WINAPI Options(HWND hDlg, UINT message, WPARAM wParam,
  207.                                         LPARAM lParam);
  208.  
  209. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  210.                          LPSTR lpszCmdLine, int cmdShow)
  211. {
  212.      MSG   msg;
  213.  
  214.      // Go init this application.
  215.      InitSound(hInstance, hPrevInstance,
  216.                   lpszCmdLine, cmdShow);
  217.  
  218.      if (lstrlen(lpszCmdLine)>1) {
  219.      CMDLINE=TRUE;
  220.      if (WaveP(lpszCmdLine))
  221.          PostMessage(hWnd, WM_CMDLINEFILE, 0,
  222.                      (LPARAM) lpszCmdLine);
  223.      else
  224.          PostMessage(hWnd, WM_CMDLINEFILE, 1,
  225.                      (LPARAM) lpszCmdLine);
  226.      }
  227.      // Get and dispatch messages for this applicaton.
  228.      while (GetMessage(&msg, NULL, 0, 0))
  229.      {
  230.           TranslateMessage(&msg);
  231.           DispatchMessage(&msg);
  232.      }
  233.      return(msg.wParam);
  234. }
  235.  
  236.  
  237. //*******************************************************************
  238. // InitSound - init the Sound application
  239. //
  240. // paramaters:
  241. //             hInstance     - The instance of this instance of this
  242. //                             application.
  243. //             hPrevInstance - The instance of the previous instance
  244. //                             of this application. This will be 0
  245. //                             if this is the first instance.
  246. //             lpszCmdLine   - A long pointer to the command line that
  247. //                             started this application.
  248. //             cmdShow       - Indicates how the window is to be shown
  249. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  250. //                             SW_MIMIMIZE.
  251. //
  252. //*******************************************************************
  253. #pragma argsused
  254. void InitSound(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  255.                     LPSTR lpszCmdLine, int cmdShow)
  256. {
  257.      InitSoundFirst(hInstance);
  258.      InitSoundEvery(hInstance, cmdShow);  // initialization for all instances
  259. }
  260.  
  261. //*******************************************************************
  262. // InitSoundFirst - done only for first instance of Sounder
  263. //
  264. // paramaters:
  265. //             hInstance     - The instance of this instance of this
  266. //                             application.
  267. //
  268. //*******************************************************************
  269. void InitSoundFirst(HINSTANCE hInstance)
  270.  
  271. {
  272.      WNDCLASS wcSoundClass;
  273.  
  274.      // Get string from resource with application name.
  275.      LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 20);
  276.  
  277.      // Define the window class for this application.
  278.      wcSoundClass.lpszClassName = SetUpData.szAppName;
  279.      wcSoundClass.hInstance     = hInstance;
  280.      wcSoundClass.lpfnWndProc   = SounderWndProc;
  281.      wcSoundClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  282.      wcSoundClass.hIcon         = LoadIcon(hInstance,
  283.                                                         MAKEINTRESOURCE(ICON_2));
  284.      wcSoundClass.lpszMenuName  = MAKEINTRESOURCE(MENU_1);
  285.      wcSoundClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
  286.      wcSoundClass.style         = CS_HREDRAW | CS_VREDRAW;
  287.      wcSoundClass.cbClsExtra    = 0;
  288.      wcSoundClass.cbWndExtra    = 0;
  289.  
  290.      // Register the class
  291.      RegisterClass(&wcSoundClass);
  292. }
  293.  
  294. //*******************************************************************
  295. // InitSoundEvery - done for every instance of Sound
  296. //
  297. // parameters:
  298. //             hInstance     - The instance of this instance of this
  299. //                             application.
  300. //             cmdShow       - Indicates how the window is to be shown
  301. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  302. //                             SW_MIMIMIZE.
  303. //
  304. //*******************************************************************
  305. void InitSoundEvery(HINSTANCE hInstance, int cmdShow)
  306. {
  307.      int i;
  308.      for(i=0; i<256; i++)
  309.         PlayList[i]=NULL;
  310.      Cur_Index=0;
  311.      Max_Index=0;
  312.  
  313.      hInst = hInstance;       // save for use by window procs
  314.  
  315.      InitCommonControls();
  316.  
  317.      // Create applications main window.
  318.      hWnd =     CreateWindow(
  319.                         SetUpData.szAppName,     // window class name
  320.                         SetUpData.szAppName,     // window title
  321.                         WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU |
  322.                         WS_THICKFRAME,     // type of window
  323.                         100,                 // x  window location
  324.                         100,                     // y
  325.                         283,                 // cx and size
  326.                         135,                     // cy
  327.                         NULL,                    // no parent for this window
  328.                         NULL,                    // use the main menu
  329.                         hInstance,               // who created this window
  330.                         NULL                     // no parms to pass on
  331.                         );
  332.  
  333.      // Update display of main window.
  334.      mainmenu=GetMenu(hWnd);
  335.  
  336.      ShowWindow(hWnd, cmdShow);
  337.      UpdateWindow(hWnd);
  338.  
  339. /*
  340. Note the initialization method of the above string.  The GetOpenFileName()
  341. function expects to find a string in the OPENFILENAME structure that has
  342. a '\0' terminator between strings and an extra '\0' that terminates the
  343. entire filter data set.  Using the technique shown below will fail because
  344. "X" is really 'X' '\0' '\0' '\0' in memory.  When the GetOpenFileName()
  345. function scans szTemp it will stop after finding the extra trailing '\0'
  346. characters.
  347.  
  348.   char szTemp[][4] = { "X", "*.*", "ABC", "*.*", "" };
  349.  
  350. The string should be "X\0*.*\0ABC\0*.*\0".
  351.  
  352. Remember that in C or C++ a quoted string is automatically terminated with
  353. a '\0' character so   char "X\0";   would result in 'X' '\0' '\0' which
  354. provides the extra '\0' that GetOpenFileName() needs to see in order to
  355. terminate the scan of the string.  Just 'char ch "X";' would result in 'X'
  356. '\0' and GetOpenFileName() would wander off in memory until it lucked into
  357. a '\0' '\0' character sequence.
  358. */
  359.  
  360. /*
  361. Some Windows structures require the size of themselves in an effort to
  362. provide backward compatibility with future versions of Windows.  If the
  363. lStructSize member is not set the call to GetOpenFileName() will fail.
  364. */
  365.  
  366.   ofnTemp.lStructSize = sizeof( OPENFILENAME );
  367.   ofnTemp.hwndOwner = hWnd; // An invalid hWnd causes non-modality
  368.   ofnTemp.hInstance = 0;
  369.   ofnTemp.lpstrFilter = (LPSTR)szTemp;  // See previous note concerning string
  370.   ofnTemp.lpstrCustomFilter = NULL;
  371.   ofnTemp.nMaxCustFilter = 0;
  372.   ofnTemp.nFilterIndex = 1;
  373.   ofnTemp.lpstrFile = (LPSTR)szName;  // Stores the result in this variable
  374.   ofnTemp.nMaxFile = sizeof( szName );
  375.   ofnTemp.lpstrFileTitle = FileTitle;
  376.   ofnTemp.nMaxFileTitle = sizeof(FileTitle);
  377.   ofnTemp.lpstrInitialDir = NULL;
  378.   ofnTemp.lpstrTitle = "Open Sound File";  // Title for dialog
  379.   ofnTemp.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  380.   ofnTemp.nFileOffset = 0;
  381.   ofnTemp.nFileExtension = 0;
  382.   ofnTemp.lpstrDefExt = "MP2";
  383.   ofnTemp.lCustData = 0L;
  384.   ofnTemp.lpfnHook = NULL;
  385.   ofnTemp.lpTemplateName = NULL;
  386. }
  387.  
  388. BOOL AppFileOpen()
  389. {
  390.     DWORD Errval;
  391. /*
  392. If the call to GetOpenFileName() fails you can call CommDlgExtendedError()
  393. to retrieve the type of error that occured.
  394. */
  395.   if(!GetOpenFileName( (LPOPENFILENAME) &ofnTemp ))
  396.   {
  397.      Errval=CommDlgExtendedError();
  398.      if(Errval!=0) // 0 value means user selected Cancel
  399.      {
  400.         MessageBox(hWnd,"Could not open file.","WARNING",MB_OK|MB_ICONSTOP);
  401.      }
  402.      return(FALSE);
  403.  
  404.   }
  405.  
  406.   return(TRUE);
  407. }
  408.  
  409. char *time_string(int ms, char *dest)
  410. {
  411.     int i, j, nmlength;
  412.     int seconds, minutes;
  413.     char second_str[4];
  414.     char minute_str[4];
  415.  
  416.     minutes = ms / 60000;
  417.     seconds = ms / 1000 - minutes * 60;
  418.  
  419.     itoa(minutes, minute_str, 10);
  420.     itoa(seconds, second_str, 10);
  421.  
  422.     nmlength = 3 - lstrlen(minute_str);
  423.  
  424.     for (i=0; i < nmlength ; i++)
  425.         dest[i] = '0';
  426.  
  427.     for (i = nmlength, j=0; i<3; i++, j++)
  428.         dest[i] = minute_str[j];
  429.  
  430.     dest[3] = ':';
  431.  
  432.     nmlength = 6 - lstrlen(second_str);
  433.  
  434.     for (i=4; i < nmlength ; i++)
  435.         dest[i] = '0';
  436.  
  437.     for (i=nmlength, j=0; i<6; i++, j++)
  438.         dest[i] = second_str[j];
  439.  
  440.     dest[6]='\0';
  441.  
  442.     return (dest);
  443. }
  444.  
  445. void clear_sound()
  446. {
  447.     scrolling = FALSE;
  448.  
  449.     if (MPEG) {
  450.  
  451.         if (MPEG_Thread) {
  452.             TerminateThread(MPEG_Thread,0L);
  453.             CloseHandle(MPEG_Thread);
  454.             MPEG_Thread=NULL;
  455.         }
  456.  
  457.         waveOutReset(*phwo);
  458.         waveOutClose(*phwo);
  459.  
  460.         if (maplay_args->stream) {
  461.             delete maplay_args->stream;
  462.             maplay_args->stream = NULL;
  463.             delete maplay_args->MPEGheader;
  464.             maplay_args->MPEGheader = NULL;
  465.             delete maplay_args->crc;
  466.             maplay_args->crc = NULL;
  467.         }
  468.  
  469.     } else {
  470.  
  471.         if (MCI_Thread) {
  472.             TerminateThread(MCI_Thread, 0L);
  473.             CloseHandle(MCI_Thread);
  474.             MCI_Thread = NULL;
  475.         }
  476.  
  477.         mciSendString ((LPSTR)"stop sounder", NULL, 0, NULL);
  478.         mciSendString ((LPSTR)"close sounder", NULL, 0, NULL);
  479.     }
  480.  
  481.     SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Stopped");
  482.     SendMessage(status_bar, SB_SETTEXT, 2, (WPARAM) "000:00");
  483.  
  484.     return;
  485. }
  486.  
  487. void ok_play()
  488. {
  489.     can_play=TRUE;
  490.     can_pause=FALSE;
  491.     playing=FALSE;
  492.     EnableMenuItem(mainmenu,CM_AUDIOPLAY, MF_ENABLED);
  493.     EnableWindow(playbut, TRUE);
  494.     EnableMenuItem(mainmenu,CM_AUDIOPAUSE, MF_GRAYED);
  495.     EnableWindow(pausebut, FALSE);
  496.     return;
  497. }
  498.  
  499. void no_play()
  500. {
  501.     can_play=FALSE;
  502.     can_pause=TRUE;
  503.     can_stop=TRUE;
  504.     playing=TRUE;
  505.     EnableMenuItem(mainmenu,CM_AUDIOPLAY, MF_GRAYED);
  506.     EnableWindow(playbut, FALSE);
  507.     EnableMenuItem(mainmenu,CM_AUDIOPAUSE, MF_ENABLED);
  508.     EnableWindow(pausebut, TRUE);
  509.     EnableMenuItem(mainmenu,CM_AUDIOSTOP, MF_ENABLED);
  510.     EnableWindow(stopbut, TRUE);
  511.     return;
  512. }
  513.  
  514. void no_stop()
  515. {
  516.     can_stop=FALSE;
  517.     EnableMenuItem(mainmenu,CM_AUDIOSTOP, MF_GRAYED);
  518.     EnableWindow(stopbut, FALSE);
  519.     return;
  520. }
  521.  
  522. BOOL reinit_MPEG()
  523. {
  524.     MPEG = TRUE;
  525.     args = maplay_args;
  526.  
  527.     maplay_args->stream= new Ibitstream(szName, hWnd);
  528.     maplay_args->MPEGheader= new Header;
  529.     maplay_args->crc = new Crc16;
  530.     maplay_args->phwo=phwo;
  531.     maplay_args->hWnd=hWnd;
  532.     maplay_args->which_c=mode;
  533.     maplay_args->position_change = FALSE;
  534.  
  535.     if (!maplay_args->MPEGheader->read_header (maplay_args->stream,
  536.                                                             &maplay_args->crc)) {
  537.         MessageBox(hWnd, "No header found!",
  538.         "File format error", MB_OK|MB_ICONSTOP);
  539.         return(FALSE);
  540.     }
  541.  
  542.     scroll_range = maplay_args->MPEGheader->min_number_of_frames(maplay_args->stream);
  543.     line_size = scroll_range >> 3;
  544.  
  545.     SendMessage(tracker, TBM_SETRANGEMIN, FALSE, 0);
  546.     SendMessage(tracker, TBM_SETRANGEMAX, FALSE, scroll_range);
  547.     SendMessage(tracker, TBM_SETPOS, TRUE, 0);
  548.     SendMessage(tracker, TBM_SETTICFREQ, scroll_range>>4, 1);
  549.     SendMessage(tracker, TBM_SETLINESIZE, 0, line_size);
  550.  
  551.     EnableMenuItem(mainmenu,CM_AUDIOPROPERTIES, MF_ENABLED);
  552.     EnableMenuItem(mainmenu,CM_OPTIONS, MF_ENABLED);
  553.     EnableWindow(tracker, TRUE);
  554.  
  555.     return(TRUE);
  556. }
  557.  
  558. BOOL reinit_MCI()
  559. {
  560.     MPEG=FALSE;
  561.  
  562.     EnableMenuItem(mainmenu,CM_AUDIOPROPERTIES, MF_GRAYED);
  563.     EnableMenuItem(mainmenu,CM_OPTIONS, MF_GRAYED);
  564.  
  565.     lstrcpy(command, "open ");
  566.     lstrcat(command, szName);
  567.     lstrcat(command, " alias sounder wait");
  568.     mciSendString ((LPSTR)command, Buffer, 1024, NULL);
  569.     mciSendString("set sounder time format ms wait", Buffer, 1024, NULL);
  570.     mciSendString("status sounder length wait", Buffer, 1024, NULL);
  571.  
  572.     scroll_range = atoi(Buffer);
  573.     line_size = scroll_range >> 3;
  574.  
  575.     args = mci_args;
  576.     mci_args->playing = FALSE;
  577.     mci_args->position_change = FALSE;
  578.     mci_args->desired_position = 0;
  579.     mci_args->hWnd = hWnd;
  580.  
  581.     SendMessage(tracker, TBM_SETRANGEMIN, FALSE, 0);
  582.     SendMessage(tracker, TBM_SETRANGEMAX, FALSE, scroll_range);
  583.     SendMessage(tracker, TBM_SETPOS, TRUE, 0);
  584.     SendMessage(tracker, TBM_SETTICFREQ, scroll_range>>4, 1);
  585.     SendMessage(tracker, TBM_SETLINESIZE, 0, line_size);
  586.     EnableWindow(tracker, TRUE);
  587.  
  588.     return (TRUE);
  589. }
  590.  
  591.  
  592. BOOL WaveP(LPSTR t)
  593. // Check if the file is a format the Windows multimedia system supports.
  594. {
  595.     return ((lstrcmp(t + lstrlen(t)-3, "WAV")==0) ||
  596.               (lstrcmp(t + lstrlen(t)-3, "wav")==0) ||
  597.               (lstrcmp(t + lstrlen(t)-3, "MID")==0) ||
  598.               (lstrcmp(t + lstrlen(t)-3, "mid")==0));
  599. }
  600.  
  601. BOOL ListP(LPSTR t)
  602. {
  603.     return ((lstrcmp(t + lstrlen(t)-3, "TXT")==0) ||
  604.               (lstrcmp(t + lstrlen(t)-3, "txt")==0));
  605. }
  606.  
  607.  
  608. LPSTR Proper_Filename(LPSTR s)
  609. {
  610.     int i;
  611.     int length=lstrlen(s);
  612.  
  613.     for(i=length; i>=0; --i)
  614.         if (s[i]=='\\')
  615.             return (s+i+1);
  616.     return(s);
  617. }
  618.  
  619. void DisplayName(LPSTR name)
  620. {
  621.  
  622.     LoadString(hInst, IDS_NAME, (LPSTR) TitleText, 64);
  623.     lstrcat(TitleText, " - [");
  624.     if (name)
  625.         lstrcat(TitleText, Proper_Filename(name));
  626.     else
  627.         lstrcat(TitleText, FileTitle);
  628.  
  629.     lstrcat(TitleText, "]");
  630.     SetWindowText(hWnd, (LPCTSTR) TitleText);
  631.     return;
  632. }
  633.  
  634. BOOL MPEG_play()
  635. // Assumes stream, MPEGheader, crc are already initialized
  636. {
  637.     BOOL t;
  638.     MPEG_Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) maplay,
  639.                                          maplay_args,0,&dwThreadId);
  640.     t=SetThreadPriority(MPEG_Thread, THREAD_PRIORITY_ABOVE_NORMAL);
  641.     return(t);
  642. }
  643.  
  644. BOOL MCI_play()
  645. {
  646.     mci_args->playing = TRUE;
  647.  
  648.     mciSendString ((LPSTR)"play sounder notify", Buffer, 1024, hWnd);
  649.  
  650.     MCI_Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mciplay,
  651.                                       mci_args, 0, &dwThreadId);
  652.     return(TRUE);
  653. }
  654.  
  655. BOOL Get_File_List(LPSTR listname)
  656. {
  657.     ifstream f((const char *) listname);
  658.     Max_Index=0;
  659.  
  660.     while(!(f.bad() || f.eof() || f.fail() || Max_Index>255)) {
  661.         if (PlayList[Max_Index]) {
  662.             delete PlayList[Max_Index];
  663.         }
  664.         PlayList[Max_Index]=new char [256];
  665.         f.getline(PlayList[Max_Index], 256, '\n');
  666.         if ((lstrlen(PlayList[Max_Index])>1) &&
  667.              (GetFileAttributes(PlayList[Max_Index])!=0xFFFFFFFF))
  668.             Max_Index++;
  669.     }
  670.  
  671.     f.close();
  672.  
  673.     lstrcpy(playlist_filename, "Track 1: ");
  674.     lstrcat(playlist_filename, Proper_Filename(PlayList[0]));
  675.     SendMessage(status_bar,SB_SETTEXT, 1,(LPARAM) playlist_filename);
  676.  
  677.     return(TRUE);
  678. }
  679.  
  680. BOOL File_Init()
  681. {
  682.     return (WaveP(szName) ? reinit_MCI() : reinit_MPEG());
  683. }
  684.  
  685. void Next_Song()
  686. {
  687.     if (++Cur_Index<Max_Index) {
  688.         lstrcpy(szName, PlayList[Cur_Index]);
  689.         if (File_Init()) {
  690.             ok_play();
  691.             no_stop();
  692.             lstrcpy(playlist_filename, "Track ");
  693.             lstrcat(playlist_filename, itoa(Cur_Index + 1, scratch, 10));
  694.             lstrcat(playlist_filename, ": ");
  695.             lstrcat(playlist_filename, Proper_Filename(szName));
  696.             SendMessage(status_bar,SB_SETTEXT, 1,(LPARAM) playlist_filename);
  697.             audio_play();
  698.         }
  699.  
  700.     } else {
  701.         if (CMDLINE)
  702.             leave();
  703.  
  704.         lstrcpy(playlist_filename, "Track 1: ");
  705.         lstrcat(playlist_filename, Proper_Filename(PlayList[0]));
  706.         SendMessage(status_bar,SB_SETTEXT, 1,(LPARAM) playlist_filename);
  707.         SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Ready");
  708.  
  709.         Cur_Index = 0;
  710.         lstrcpy(szName, PlayList[0]);
  711.         if (File_Init()) {
  712.             ok_play();
  713.             no_stop();
  714.             if (Repeat)
  715.                 audio_play();
  716.         }
  717.     }
  718.     return;
  719. }
  720.  
  721. void Init_List()
  722. {
  723.     ListMode=TRUE;
  724.     EnableMenuItem(mainmenu,CM_LISTPREV, MF_ENABLED);
  725.     EnableWindow(prevbut, TRUE);
  726.     EnableMenuItem(mainmenu,CM_LISTREPEAT, MF_ENABLED);
  727.     EnableWindow(repbut, TRUE);
  728.     EnableMenuItem(mainmenu,CM_LISTNEXT, MF_ENABLED);
  729.     EnableWindow(nextbut, TRUE);
  730.     return;
  731. }
  732.  
  733. void gotop_List(int n)
  734. {
  735.     CMDLINE=FALSE;
  736.     clear_sound();
  737.  
  738.     Cur_Index+=n;
  739.     if (Cur_Index>=Max_Index)
  740.         Cur_Index-=Max_Index;
  741.     else if (Cur_Index<-1)
  742.         Cur_Index+=Max_Index;
  743.  
  744.     Next_Song();
  745. }
  746.  
  747. void no_list()
  748. {
  749.     int i;
  750.  
  751.     ListMode=FALSE;
  752.     EnableMenuItem(mainmenu,CM_LISTPREV, MF_GRAYED);
  753.     EnableWindow(prevbut, FALSE);
  754.     EnableMenuItem(mainmenu,CM_LISTREPEAT, MF_GRAYED);
  755.     EnableWindow(repbut, FALSE);
  756.     EnableMenuItem(mainmenu,CM_LISTNEXT, MF_GRAYED);
  757.     EnableWindow(nextbut, FALSE);
  758.  
  759.     SendMessage(status_bar,SB_SETTEXT, 1, NULL);
  760.  
  761.     for(i=0; i<Max_Index; i++)
  762.         delete PlayList[i];
  763.     Cur_Index=0;
  764.     Max_Index=0;
  765. }
  766.  
  767. void update_timewin(int num)
  768. {
  769.     if (MPEG)
  770.         SendMessage(status_bar, SB_SETTEXT, 2,
  771.                       (LPARAM) time_string((int) (num * maplay_args->MPEGheader->ms_per_frame()),
  772.                                                                 scratch));
  773.     else
  774.         SendMessage(status_bar, SB_SETTEXT, 2,
  775.                       (LPARAM) time_string(num, scratch));
  776.  
  777.     return;
  778. }
  779.  
  780.  
  781. void file_open()
  782. {
  783.     CMDLINE=FALSE;
  784.  
  785.     if (AppFileOpen()) {
  786.  
  787.     clear_sound();
  788.  
  789.     ListMode=FALSE;
  790.     if (ListP(szName)) {
  791.             Init_List();
  792.             Get_File_List(szName);
  793.             lstrcpy(szName, PlayList[0]);
  794.     } else
  795.         no_list();
  796.  
  797.     if (!File_Init())
  798.         return;
  799.  
  800.     ok_play();
  801.     no_stop();
  802.  
  803.     EnableMenuItem(mainmenu,CM_AUDIOREPEAT, MF_ENABLED);
  804.     DisplayName(NULL);
  805.     EnableWindow(rewbut, TRUE);
  806.     EnableMenuItem(mainmenu, CM_AUDIOREWIND, MF_ENABLED);
  807.     EnableWindow(ffbut, TRUE);
  808.     EnableMenuItem(mainmenu, CM_AUDIOFAST_FORWARD, MF_ENABLED);
  809.  
  810.     SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Ready");
  811.     SendMessage(status_bar, SB_SETTEXT, 2, (WPARAM) "000:00");
  812.     }
  813.     return;
  814. }
  815.  
  816. void leave()
  817. {
  818.     clear_sound();
  819.     delete maplay_args;
  820.     delete mci_args;
  821.     delete phwo;
  822.     DestroyWindow(hWnd);
  823.     return;
  824. }
  825.  
  826. void audio_play()
  827. {
  828.     if (can_play) {
  829.         no_play();
  830.  
  831.         if (MPEG) {
  832.             if (paused && MPEG_Thread!=NULL) {
  833.                 paused=FALSE;
  834.                 waveOutRestart(*phwo);
  835.                 ResumeThread(MPEG_Thread);
  836.             } else
  837.                 MPEG_play();
  838.         } else {
  839.             MCI_play();
  840.         }
  841.         SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Playing...");
  842.     }
  843.     return;
  844. }
  845.  
  846. void audio_pause()
  847. {
  848.     paused=TRUE;
  849.     CMDLINE=FALSE;
  850.  
  851.     if (MPEG) {
  852.         SuspendThread(MPEG_Thread);
  853.         waveOutPause(*phwo);
  854.     } else {
  855.         mci_args->playing = FALSE;
  856.         mciSendString ((LPSTR)"pause sounder", NULL, 0, NULL);
  857.     }
  858.     ok_play();
  859.     SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Paused");
  860.     return;
  861. }
  862.  
  863. void audio_stop()
  864. {
  865.     paused=FALSE;
  866.     CMDLINE=FALSE;
  867.     clear_sound();
  868.     File_Init();
  869.     ok_play();
  870.     no_stop();
  871.  
  872.     return;
  873. }
  874.  
  875. void audio_properties ()
  876. {
  877.      char MPEGinfo[1024];
  878.  
  879.      lstrcpy(MPEGinfo, "Layer :  ");
  880.      lstrcat(MPEGinfo, maplay_args->MPEGheader->layer_string());
  881.      lstrcat(MPEGinfo, "Checksums? : ");
  882.      lstrcat(MPEGinfo, maplay_args->MPEGheader->checksums() ?
  883.                              "Yes" : "No");
  884.      lstrcat(MPEGinfo, "\nMode : ");
  885.      lstrcat(MPEGinfo, maplay_args->MPEGheader->mode_string());
  886.      lstrcat(MPEGinfo, "Original?        : ");
  887.      lstrcat(MPEGinfo, maplay_args->MPEGheader->original() ?
  888.                              "Yes" : "No");
  889.      lstrcat(MPEGinfo, "\nSample Frequency : ");
  890.      lstrcat(MPEGinfo, maplay_args->MPEGheader->sample_frequency_string ());
  891.      lstrcat(MPEGinfo, "Copyright?     : ");
  892.      lstrcat(MPEGinfo, maplay_args->MPEGheader->copyright() ?
  893.                              "Yes" : "No");
  894.      lstrcat(MPEGinfo, "\nBitrate: ");
  895.      lstrcat(MPEGinfo, maplay_args->MPEGheader->bitrate_string());
  896.  
  897.      lstrcat(MPEGinfo, "\n\nFrames  :  ");
  898.      lstrcat(MPEGinfo, itoa(scroll_range, scratch, 10));
  899.      lstrcat(MPEGinfo, "\nFile Size : ");
  900.      lstrcat(MPEGinfo, itoa(maplay_args->stream->file_size() >> 10,
  901.                              scratch, 10));
  902.      lstrcat(MPEGinfo, " KB");
  903.  
  904.      MessageBox(hWnd, MPEGinfo, "MPEG Properties",
  905.                     MB_OK | MB_ICONINFORMATION    );
  906. }
  907.  
  908. void about()
  909. {
  910.     MessageBox(hWnd,
  911. "maplay 1.2+ for Win32 version 1.70 (08/01/96) - Pentium build.\n\n \
  912. A Full Quality MPEG Audio \
  913. Layer 1 and 2 Decoder for Windows 95 and NT.\n\nCopyright (C) 1993, 1994 \
  914. Tobias Bading (bading@cs.tu-berlin.de)\nBerlin University of Technology \
  915. \nCreated: 6/23/94 14:12:46\n\nInterface and Win32 port by Jeff \
  916. Tsay (ctsay@pasteur.eecs.berkeley.edu).\n\nThis program is free software. \
  917. See the GNU General Public License in the \nfile COPYING for more details.",
  918.                      "About maplay 1.2+ for Win32", MB_OK);
  919.     return;
  920. }
  921.  
  922. #pragma argsused
  923. LRESULT APIENTRY SounderWndProc(HWND hWnd, UINT message,
  924.                                           WPARAM wParam, LPARAM lParam)
  925. {
  926.      BOOL disabled, selected;
  927.      int new_pos;
  928.  
  929.      switch (message)
  930.      {
  931.           case WM_CREATE:
  932.           openbut= CreateWindow ("BUTTON", NULL,
  933.                       WS_CHILD| WS_VISIBLE | WS_TABSTOP |
  934.                       BS_OWNERDRAW | BS_PUSHBUTTON,
  935.                       5, 5, 24, 24,
  936.                       hWnd, (HMENU)CM_FILEOPEN, hInst, NULL);
  937.  
  938.           playbut= CreateWindow ("BUTTON", NULL,
  939.                       WS_CHILD | WS_VISIBLE | WS_DISABLED |
  940.                       WS_TABSTOP | BS_OWNERDRAW | BS_PUSHBUTTON,
  941.                       45, 5, 24, 24,
  942.                       hWnd, (HMENU)CM_AUDIOPLAY, hInst,
  943.                       NULL);
  944.  
  945.           pausebut= CreateWindow ("BUTTON", NULL,
  946.                         WS_CHILD| WS_VISIBLE| WS_DISABLED |
  947.                         WS_TABSTOP | BS_OWNERDRAW | BS_PUSHBUTTON,
  948.                         69, 5, 24, 24,
  949.                         hWnd, (HMENU)CM_AUDIOPAUSE, hInst, NULL);
  950.  
  951.           stopbut= CreateWindow ("BUTTON", NULL,
  952.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  953.                       WS_TABSTOP | BS_OWNERDRAW | BS_PUSHBUTTON,
  954.                         93, 5, 24, 24,
  955.                       hWnd, (HMENU)CM_AUDIOSTOP, hInst, NULL);
  956.  
  957.           rewbut=  CreateWindow ("BUTTON", NULL,
  958.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  959.                       WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW,
  960.                       157, 5, 24, 24,
  961.                       hWnd, (HMENU)CM_AUDIOREWIND, hInst, NULL);
  962.  
  963. /*          repbut=  CreateWindow ("BUTTON", NULL,
  964.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  965.                       WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW,
  966.                       157, 5, 24, 24,
  967.                       hWnd, (HMENU)CM_LISTREPEAT, hInst, NULL); */
  968.  
  969.              ffbut= CreateWindow ("BUTTON", NULL,
  970.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  971.                       WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW,
  972.                       181, 5, 24, 24,
  973.                       hWnd, (HMENU)CM_AUDIOFAST_FORWARD, hInst, NULL);
  974.  
  975.           prevbut= CreateWindow ("BUTTON", NULL,
  976.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  977.                       WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW,
  978.                       133, 5, 24, 24,
  979.                       hWnd, (HMENU)CM_LISTPREV, hInst, NULL);
  980.  
  981.           nextbut= CreateWindow ("BUTTON", NULL,
  982.                       WS_CHILD| WS_VISIBLE | WS_DISABLED |
  983.                       WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW,
  984.                       205, 5, 24, 24,
  985.                       hWnd, (HMENU)CM_LISTNEXT, hInst, NULL);
  986.  
  987.          aboutbut= CreateWindow ("BUTTON", NULL,
  988.                       WS_CHILD| WS_VISIBLE | WS_TABSTOP |
  989.                       BS_PUSHBUTTON | BS_OWNERDRAW,
  990.                       245, 5, 24, 24,
  991.                       hWnd, (HMENU)CM_HELPABOUT, hInst, NULL);
  992.  
  993.           tracker= CreateWindow(TRACKBAR_CLASS, NULL,
  994.                       WS_CHILD | WS_VISIBLE | WS_TABSTOP |
  995.                       WS_DISABLED | TBS_AUTOTICKS,
  996.                       5, 34, 263, 30, hWnd, (HMENU) 8, hInst,  NULL);
  997.  
  998.       status_bar= CreateStatusWindow(WS_CHILD | WS_VISIBLE | SBT_NOBORDERS,
  999.                       "No file", hWnd, 0);
  1000.  
  1001.           SendMessage(status_bar, SB_SETPARTS, 4, (LPARAM) panes);
  1002.           return(DefWindowProc(hWnd, message, wParam, lParam));
  1003.  
  1004.           case WM_DRAWITEM:
  1005.           hdc=GetDC(hWnd);
  1006.           dis = (DRAWITEMSTRUCT *) lParam;
  1007.           disabled = (dis->itemState & ODS_DISABLED) == ODS_DISABLED;
  1008.           selected = (dis->itemState & ODS_SELECTED) == ODS_SELECTED;
  1009.  
  1010.           switch (dis->CtlType) {
  1011.  
  1012.           case ODT_BUTTON:
  1013.           if (dis->hwndItem==openbut)
  1014.             if (selected)
  1015.                     DrawIcon(hdc, 5, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_9)));
  1016.             else
  1017.                 DrawIcon(hdc, 5, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_12)));
  1018.           else if (dis->hwndItem == playbut)
  1019.             if (disabled)
  1020.                 DrawIcon(hdc, 45, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_14)));
  1021.             else
  1022.                 if (selected)
  1023.                     DrawIcon(hdc, 45, 5, LoadIcon(hInst,MAKEINTRESOURCE(ICON_18)));
  1024.                 else
  1025.                     DrawIcon(hdc, 45, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_13)));
  1026.           else if (dis->hwndItem == pausebut)
  1027.             if (disabled)
  1028.               DrawIcon(hdc, 69, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_4)));
  1029.             else
  1030.                 if (selected)
  1031.                   DrawIcon(hdc, 69, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_24)));
  1032.                 else
  1033.                   DrawIcon(hdc, 69, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_6)));
  1034.           else if (dis->hwndItem == stopbut)
  1035.             if (disabled)
  1036.               DrawIcon(hdc, 93, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_3)));
  1037.             else
  1038.               if (selected)
  1039.                   DrawIcon(hdc, 93, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_10)));
  1040.               else
  1041.                   DrawIcon(hdc, 93, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_5)));
  1042.           else if (dis->hwndItem == aboutbut)
  1043.               if (selected)
  1044.                 DrawIcon(hdc, 245, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_21)));
  1045.               else
  1046.                 DrawIcon(hdc, 245, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_15)));
  1047.           else if (dis->hwndItem == rewbut)
  1048.             if (disabled)
  1049.                 DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_8)));
  1050.             else
  1051.                 if (selected)
  1052.                     DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_22)));
  1053.                 else
  1054.                     DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_7)));
  1055. /*          else if (dis->hwndItem == repbut)
  1056.             if (disabled)
  1057.                 DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_19)));
  1058.             else
  1059.                 if (selected)
  1060.                     DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_11)));
  1061.                 else
  1062.                     DrawIcon(hdc, 157, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_25))); */
  1063.           else if (dis->hwndItem == ffbut)
  1064.             if (disabled)
  1065.                 DrawIcon(hdc, 181, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_17)));
  1066.             else
  1067.                 if (selected)
  1068.                     DrawIcon(hdc, 181, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_23)));
  1069.                 else
  1070.                     DrawIcon(hdc, 181, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_16)));
  1071.  
  1072.           else if (dis->hwndItem == prevbut)
  1073.             if (disabled)
  1074.                 DrawIcon(hdc, 133, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_26)));
  1075.             else
  1076.                 if (selected)
  1077.                     DrawIcon(hdc, 133, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_27)));
  1078.                 else
  1079.                     DrawIcon(hdc, 133, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_20)));
  1080.           else if (dis->hwndItem == nextbut)
  1081.             if (disabled)
  1082.                 DrawIcon(hdc, 205, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_29)));
  1083.             else
  1084.                 if (selected)
  1085.                     DrawIcon(hdc, 205, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_30)));
  1086.                 else
  1087.                     DrawIcon(hdc, 205, 5, LoadIcon(hInst, MAKEINTRESOURCE(ICON_28)));
  1088.           break;
  1089.           }
  1090.  
  1091.           ReleaseDC(hWnd, hdc);
  1092.           return(DefWindowProc(hWnd, message, wParam, lParam));
  1093.  
  1094.           case WM_COMMAND:
  1095.                 switch (GET_WM_COMMAND_ID(wParam, lParam))
  1096.                 {
  1097.                      case CM_FILEOPEN:
  1098.                      file_open();
  1099.                      break;
  1100.  
  1101.                      case CM_FILEEXIT:
  1102.                      leave();
  1103.                      break;
  1104.  
  1105.                      case CM_AUDIOPLAY:
  1106.                      audio_play();
  1107.                      break;
  1108.  
  1109.                      case CM_AUDIOPAUSE:
  1110.                      audio_pause();
  1111.                      break;
  1112.  
  1113.                      case CM_AUDIOSTOP:
  1114.                      audio_stop();
  1115.                      break;
  1116.  
  1117.                      case CM_AUDIOREWIND:
  1118.                      CMDLINE = FALSE;
  1119.                      scrolling = TRUE;
  1120.  
  1121.                      new_pos = SendMessage(tracker, TBM_GETPOS, 0, 0);
  1122.                      if ((new_pos -= line_size) < 0)
  1123.                             new_pos = 0;
  1124.  
  1125.                      args->desired_position = new_pos;
  1126.  
  1127.                      if (!args->position_change) {
  1128.                         args->position_change = TRUE;
  1129.                         if (!paused && playing)
  1130.                             SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Seeking...");
  1131.                      }
  1132.  
  1133.                      SendMessage(tracker, TBM_SETPOS, (WPARAM) TRUE, new_pos);
  1134.                      break;
  1135.  
  1136.                      case CM_AUDIOFAST_FORWARD:
  1137.                      CMDLINE = FALSE;
  1138.  
  1139.                      new_pos = SendMessage(tracker, TBM_GETPOS, 0, 0);
  1140.                      if ((new_pos += line_size) < scroll_range) {
  1141.                             args->desired_position = new_pos;
  1142.                             scrolling = TRUE;
  1143.  
  1144.                             if (!args->position_change) {
  1145.                             args->position_change = TRUE;
  1146.                             if (!paused && playing)
  1147.                                 SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Seeking...");
  1148.                             }
  1149.  
  1150.                             SendMessage(tracker, TBM_SETPOS, (WPARAM) TRUE, new_pos);
  1151.                      }
  1152.                      break;
  1153.  
  1154.  
  1155.                      case CM_AUDIOREPEAT:
  1156.                      CMDLINE=FALSE;
  1157.                      // Beautiful C++ style, but Borland doesn't like this:
  1158.  
  1159.                      if (Repeat=!Repeat) {
  1160.                         CheckMenuItem(mainmenu, CM_AUDIOREPEAT, MF_CHECKED);
  1161.                         SendMessage(status_bar,SB_SETTEXT, 3,(LPARAM) "R");
  1162.                      } else {
  1163.                         CheckMenuItem(mainmenu, CM_AUDIOREPEAT, MF_UNCHECKED);
  1164.                         SendMessage(status_bar,SB_SETTEXT, 3,(LPARAM) NULL);
  1165.                      }
  1166.                      break;
  1167.  
  1168.                      case CM_OPTIONS:
  1169.                      if (DialogBox(hInst, MAKEINTRESOURCE(OPTIONS), hWnd,
  1170.                                   Options)==-1)
  1171.                           MessageBox(hWnd, "Unable to open options dialog box.",
  1172.                             "Error Opening Dialog Box", MB_OK);
  1173.                      break;
  1174.  
  1175.                      case CM_AUDIOPROPERTIES:
  1176.                      audio_properties();
  1177.                      break;
  1178.  
  1179.                      case CM_LISTPREV:
  1180.                      gotop_List(-2);
  1181.                      break;
  1182.  
  1183.                      case CM_LISTREPEAT:
  1184.                      gotop_List(-1);
  1185.                      break;
  1186.  
  1187.                      case CM_LISTNEXT:
  1188.                      gotop_List(0);
  1189.                      break;
  1190.  
  1191.                      case CM_HELPABOUT:
  1192.                      about();
  1193.                      break;
  1194.  
  1195.                      default:
  1196.                      break;
  1197.                 }
  1198.              break;
  1199.  
  1200.           case WM_HSCROLL:
  1201.                 // Process scroll messages by sending notification to
  1202.                 // appropriate thread.
  1203.                 LRESULT new_pos;
  1204.  
  1205.                 switch (LOWORD(wParam)) {
  1206.                     case TB_LINEUP:
  1207.                     case TB_LINEDOWN:
  1208.                     case TB_PAGEDOWN:
  1209.                     case TB_PAGEUP:
  1210.                     CMDLINE = FALSE;
  1211.                     new_pos = SendMessage(tracker, TBM_GETPOS, 0, 0);
  1212.  
  1213.                     if ((new_pos  < scroll_range) && (new_pos>=0)) {
  1214.                         scrolling = TRUE;
  1215.                         args->desired_position = new_pos;
  1216.  
  1217.                         if (!args->position_change) {
  1218.                             args->position_change = TRUE;
  1219.                             if (!paused && playing)
  1220.                                 SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Seeking...");
  1221.                         }
  1222.                     }
  1223.                     break;
  1224.  
  1225.                     case TB_THUMBTRACK:
  1226.                     scrolling = TRUE;        // We are scrolling, don't allow
  1227.                                                 // scroll position changes by threads.
  1228.                     new_pos = SendMessage(tracker, TBM_GETPOS, 0, 0);
  1229.                     update_timewin((int) new_pos);
  1230.                     break;
  1231.  
  1232.                     case TB_THUMBPOSITION:    // Scroll box placed somewhere
  1233.                     args->desired_position = SendMessage(tracker, TBM_GETPOS, 0, 0);
  1234.  
  1235.                     if(!args->position_change) {
  1236.                         args->position_change = TRUE;
  1237.                         if (!paused && playing)
  1238.                             SendMessage(status_bar,SB_SETTEXT, 0, (LPARAM) "Seeking...");
  1239.                     }
  1240.                     break;
  1241.                 }
  1242.                 return(0L);
  1243.  
  1244.           case SCROLL_POS:    // Process new position data from threads.
  1245.           if (!scrolling && (wParam <=scroll_range)) {
  1246.                 SendMessage(tracker, TBM_SETPOS, TRUE, wParam);
  1247.                 update_timewin((int) wParam);
  1248.           }
  1249.           return(0L);
  1250.  
  1251.           case SEEK_ACK:        // Seek completed, allow scroll changes.
  1252.           SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Playing...");
  1253.           scrolling = FALSE;
  1254.           return(0L);
  1255.  
  1256.           case MM_MCINOTIFY:
  1257.                 switch (wParam) {
  1258.                     case MCI_NOTIFY_SUCCESSFUL:
  1259.                     clear_sound();
  1260.  
  1261.                     if (ListMode) {
  1262.                         Next_Song();
  1263.                         return(0L);
  1264.                     }
  1265.  
  1266.                     reinit_MCI();
  1267.                     ok_play();
  1268.                     no_stop();
  1269.  
  1270.                     if (Repeat) {
  1271.                         no_play();
  1272.                         MCI_play();
  1273.                         SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Playing...");
  1274.                     } else {
  1275.                         playing=FALSE;
  1276.                         if (CMDLINE)
  1277.                             leave();
  1278.                         SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Stopped");
  1279.                     }
  1280.                     break;
  1281.                 }
  1282.           break;
  1283.  
  1284.           case WM_DESTROY:
  1285.           PostQuitMessage(0);   // this is the end...
  1286.           break;
  1287.  
  1288.           case WM_CLOSE:
  1289.           // Tell windows to destroy our window.
  1290.           leave();
  1291.           break;
  1292.  
  1293.           case WM_THREADEND:
  1294.  
  1295.           clear_sound();
  1296.  
  1297.           if (ListMode) {
  1298.               Next_Song();
  1299.               return(0L);
  1300.           }
  1301.  
  1302.           if (CMDLINE)
  1303.               leave();
  1304.           else {
  1305.               playing=FALSE;
  1306.               reinit_MPEG(); // We know file is ok already.
  1307.  
  1308.               if (Repeat) {
  1309.                   MPEG_play();
  1310.                   SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Playing...");
  1311.               } else {
  1312.                   ok_play();
  1313.                   no_stop();
  1314.                   SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Stopped");
  1315.               }
  1316.           }
  1317.           break;
  1318.  
  1319.           case WM_CMDLINEFILE:
  1320.           lstrcpy(szName, (LPSTR) lParam);
  1321.           if (wParam == 0) {
  1322.                 playing=TRUE;
  1323.                 no_play();
  1324.                 reinit_MCI();
  1325.                 MCI_play();
  1326.           } else {
  1327.               clear_sound();
  1328.               if (!reinit_MPEG())
  1329.                     return(1L);
  1330.               playing=FALSE;
  1331.               no_play();
  1332.               MPEG_play();
  1333.           }
  1334.           SendMessage(status_bar,SB_SETTEXT, 0,(LPARAM) "Playing...");
  1335.           DisplayName(szName);
  1336.           EnableWindow(rewbut, TRUE);
  1337.           EnableMenuItem(mainmenu, CM_AUDIOREWIND, MF_ENABLED);
  1338.           EnableWindow(ffbut, TRUE);
  1339.           EnableMenuItem(mainmenu, CM_AUDIOFAST_FORWARD, MF_ENABLED);
  1340.           break;
  1341.  
  1342.           case WM_CHAR:
  1343.             switch(wParam) {
  1344.                 case 'o':
  1345.                 file_open();
  1346.                 break;
  1347.  
  1348.                 case ' ':
  1349.                 audio_play();
  1350.                 break;
  1351.  
  1352.                 case 's':
  1353.                 audio_stop();
  1354.                 break;
  1355.  
  1356.                 case '"':
  1357.                 case 'p':
  1358.                 audio_pause();
  1359.                 break;
  1360.  
  1361.                 case '?':
  1362.                 about();
  1363.                 break;
  1364.  
  1365.                 case 'x':
  1366.                 case 'q':
  1367.                 leave();
  1368.                 break;
  1369.             }
  1370.           break;
  1371.  
  1372.           case 312:        // CTLCOLOR message for trackbar
  1373.           if ((HWND) lParam == tracker)
  1374.               return((DWORD) GetStockObject(LTGRAY_BRUSH));
  1375.  
  1376.           default:
  1377.              // Let windows handle all messages we choose to ignore.
  1378.              return(DefWindowProc(hWnd, message, wParam, lParam));
  1379.      }
  1380.      return(0L);
  1381. }
  1382.  
  1383. void leave_options(HWND hDlg)
  1384. {
  1385.     enum e_channels old_mode=mode;
  1386.  
  1387.     if (IsDlgButtonChecked(hDlg, IDC_STEREO))
  1388.         mode=both;
  1389.     else if (IsDlgButtonChecked(hDlg, IDC_LEFT))
  1390.         mode=left;
  1391.     else
  1392.         mode=right;
  1393.  
  1394.     if ((mode!=old_mode) && !(playing || paused))
  1395.         reinit_MPEG();
  1396.  
  1397.     EndDialog(hDlg, TRUE);
  1398.  
  1399.     return;
  1400. }
  1401.  
  1402. #pragma argsused
  1403. BOOL WINAPI Options(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1404. {
  1405.      switch (message) {
  1406.  
  1407.         case WM_INITDIALOG:
  1408.  
  1409.         switch (mode) {
  1410.             case both:
  1411.             CheckRadioButton(hDlg, IDC_STEREO, IDC_RIGHT, IDC_STEREO);
  1412.             break;
  1413.  
  1414.             case left:
  1415.             CheckRadioButton(hDlg, IDC_STEREO, IDC_RIGHT, IDC_LEFT);
  1416.             break;
  1417.  
  1418.             case right:
  1419.             CheckRadioButton(hDlg, IDC_STEREO, IDC_RIGHT, IDC_RIGHT);
  1420.             break;
  1421.         }
  1422.         return(TRUE);
  1423.  
  1424.         case WM_CLOSE:
  1425.         leave_options(hDlg);
  1426.         return(TRUE);
  1427.  
  1428.         case WM_COMMAND:
  1429.         {
  1430.             switch (GET_WM_COMMAND_ID(wParam, lParam))  {
  1431.  
  1432.               case IDOK:
  1433.               leave_options(hDlg);
  1434.               return(TRUE);
  1435.  
  1436.               default:
  1437.               return(TRUE);
  1438.             }
  1439.         }
  1440.  
  1441.         case WM_CTLCOLORDLG:
  1442.         return((DWORD) GetStockObject(LTGRAY_BRUSH));
  1443.  
  1444.         default:
  1445.         return(FALSE);
  1446.      }
  1447. }
  1448.  
  1449.