home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / sysba021.zip / SRC.ZIP / sysbar2 / CD_Player / sb2_cd.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  39KB  |  1,273 lines

  1. /*
  2.  
  3.   SysBar/2 Utility Set  version 0.21
  4.  
  5.   CD Player module
  6.  
  7.   ..................................................................
  8.  
  9.   Copyright (c) 1995-99  Dmitry I. Platonoff <dip@platonoff.com>
  10.   Copyright (c) 2002,03  Max Alekseyev       <relf@os2.ru>
  11.  
  12.                            All rights reserved
  13.  
  14.   ..................................................................
  15.  
  16.   LICENSE
  17.   ~~~~~~~
  18.   Redistribution and use in source and binary forms, with or without
  19.   modification, are permitted provided that the following conditions
  20.   are met:
  21.  
  22.   1. Redistributions of source code must retain the above copyright
  23.      notice, this list of conditions and the following disclaimer.
  24.  
  25.   2. Redistributions in binary form must reproduce the above
  26.      copyright notice, this list of conditions and the following
  27.      disclaimer in the documentation and/or other materials provided
  28.      with the distribution.
  29.  
  30.   3. Redistributions of any form whatsoever, as well as all
  31.      advertising materials mentioning features or use of this
  32.      software (if any), must include the following acknowledgment:
  33.      "This product includes software developed by Dmitry I. Platonoff".
  34.  
  35.   4. The names "SysBar/2" and "Dmitry I. Platonoff" must not be
  36.      used to endorse or promote products derived from this software
  37.      without prior written permission. For such permission, please
  38.      contact dplatonoff@canada.com.
  39.  
  40.   5. Products derived from this software may not be called
  41.      "SysBar/2" nor may "Dmitry I. Platonoff" appear in their
  42.      contributor lists without prior written permission.
  43.  
  44.   ..................................................................
  45.  
  46.   DISCLAIMER
  47.   ~~~~~~~~~~
  48.   THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS "AS IS"
  49.   AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50.   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  51.   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  52.   AUTHOR OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  53.   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  54.   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  55.   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  56.   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  57.   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  58.   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59.   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60.  
  61. */
  62.  
  63. #define __IBMCPP__
  64. #define __IBMC__
  65.  
  66. #define INCL_DOSDEVICES
  67. #define INCL_DOSDEVIOCTL
  68. #define INCL_DOSPROCESS
  69. #define INCL_DOSSEMAPHORES
  70. #define INCL_GPI
  71. #define INCL_WIN
  72.  
  73. #include <os2.h>
  74. #include <process.h>
  75. #include <stdio.h>
  76. #include <stdlib.h>
  77. #include <string.h>
  78. #include "..\SysBar2.h"
  79. #include "CDengine.h"
  80. #include "SB2_CD.h"
  81. #include "SB2_CD_res.h"
  82.  
  83.  
  84. CDDrive* CurrentDrive = NULL;
  85. CDROMDeviceMap CDMap = { 0, 0 };
  86.  
  87.  
  88.  
  89. // Just a dummy data structure
  90. typedef struct
  91. {
  92.   short int iSize;
  93. } DummyData;
  94. DummyData DummyInit = { sizeof ( DummyData ) };
  95.  
  96.  
  97. inline int strcmp2( char *s1, char *s2 )
  98. {
  99.   if ( ! s1 || ! s2 ) return -1;
  100.   else return strcmp( s1, s2 );
  101. }
  102.  
  103. inline int atoi2( char *s )
  104. {
  105.   if ( s ) return atoi( s );
  106.   else return 0;
  107. }
  108.  
  109.  
  110. // Application handles
  111. HEV hev;
  112. char szSemName[] = "\\SEM32\\SB2CD_EVT";
  113. HAB hab;
  114. HWND hwCDClient1 = NULLHANDLE;
  115. HWND hwCDFrame = NULLHANDLE;
  116. HWND hmPopupMenu = NULLHANDLE;
  117. HMODULE hmSysBar2Dll = NULLHANDLE;
  118.  
  119. FATTRS fat;
  120.  
  121.  
  122. // Mode switches
  123. short int iTopmost = 1;
  124. short int bActive = 0;
  125. static short int bLastVisible = 0;
  126. short int bPlayInserted = 1;
  127. short int bFullScan = 0;
  128. short int bMonochrome = 0;
  129. short int bLockPosition = 0;
  130. short int bLarge = 0;
  131. short int iBindToCorner = 0;
  132. short int bAutodetectDrive = 0;
  133. short int bLoopDisk = 0;
  134. short int bRandomOrder = 0;
  135.  
  136. // INI-file stuff
  137. char *pszIniFile = NULL;
  138. char szSysBar2CD[] = "SysBar2_CD";
  139.  
  140. // Main window dimentions
  141. int iWindowWidth[2] = { 230, 254 };
  142. int iTimeWindowWidth[2] = { 68, 92 };
  143. int iWindowHeight[2] = { 26, 33 };
  144. int iStatusWindowY[2] = { 10, 14 };
  145. int iTrackX[2] = { 50, 70 };
  146.  
  147. // Button bitmaps
  148. const int iBBCount = 8;
  149. const int iBBHeight = 6;
  150. const int iBBWidth = 16;
  151. int iButtonWidth[2] = { 32, 32 };
  152. int iButtonHeight[2] = { 8, 12 };
  153. HBITMAP hbButtons[iBBCount];
  154. enum ButtonBitmaps
  155. {
  156.   iBBmpTime,
  157.   iBBmpLeft,
  158.   iBBmpPlay,
  159.   iBBmpEject,
  160.   iBBmpRight,
  161.   iBBmpPause,
  162.   iBBmpStop,
  163.   iBBmpClose
  164. };
  165.  
  166. // Mode bitmaps
  167. const int iMBCount = 3;
  168. const int iMBHeight = 5;
  169. const int iMBWidth = 6;
  170. HBITMAP hbModes[iMBCount][2];
  171.  
  172. const int iButtonCount = 5;
  173.  
  174. // Button class
  175. class CDButton
  176. {
  177. public:
  178.   HWND hWnd;
  179.   HBITMAP hBitmap;
  180.   ULONG uID;
  181.   int x, y, cx, cy;
  182.   CDButton( int i );
  183.   void Draw( HPS hps, short int iRaised = 1 ) 
  184.     { SB2_Button( hps, x, y, x + cx - 1, y + cy - 1, iRaised, hBitmap,
  185.       iBBWidth, iBBHeight ); }
  186.   void SizeWindow( int i );
  187. } *CDButtons[iButtonCount];
  188.  
  189. CDButton::CDButton( int i )
  190. {
  191.   uID = i + ID_CDBUTTON;
  192.   hBitmap = hbButtons[i];
  193.   hWnd = WinCreateWindow( hwCDFrame, WC_BUTTON, NULL, 
  194.     ( ULONG ) ( WS_VISIBLE | BS_USERBUTTON | BS_NOPOINTERFOCUS ),
  195.     0, 0, 0, 0, hwCDFrame, HWND_TOP, uID, NULL, NULL );
  196.   SizeWindow( i );
  197. }
  198.  
  199. void CDButton::SizeWindow( int i )
  200. {
  201.   cx = iButtonWidth[bLarge] - 1;
  202.   cy = iButtonHeight[bLarge];
  203.   x = iTimeWindowWidth[bLarge] + ( i * iButtonWidth[bLarge] );
  204.   y = 2;
  205.   WinSetWindowPos( hWnd, HWND_TOP, x, y, cx, cy,
  206.     SWP_MOVE | SWP_SIZE | SWP_SHOW );
  207. }
  208.  
  209.  
  210.  
  211. // Status messages
  212. char *pszCDMessage = NULL;
  213. //char szCDM_TrayOpened[] = "Tray is opened";
  214. char szCDM_NoDisk[] = "No CD in drive";
  215. char szCDM_MediaPresent[] = "Media present";
  216. char szCDM_NonAudio[] = "Non-audio CD inserted";
  217. char szCDM_Playing[] = "Track ";
  218. char szCDM_Paused[] = "Paused";
  219. char *pszCDMessages[] =
  220. {
  221.   szCDM_NoDisk,
  222.   szCDM_NoDisk,
  223.   szCDM_MediaPresent,
  224.   szCDM_Playing,
  225.   szCDM_Paused
  226. };
  227.  
  228. // Yes/no strings
  229. char *pszYesNo[2] = { "no", "yes" };
  230.  
  231.  
  232. // Track/playing info
  233. int iTimeMode = 0;
  234.  
  235.  
  236. void AbortStartup( void )
  237. {
  238.   PERRINFO pErrInfoBlk;
  239.   PSZ pszOffSet;
  240.   PSZ pszErrMsg;
  241.  
  242.   if ( ( pErrInfoBlk = WinGetErrorInfo( hab ) ) != ( PERRINFO ) NULL )
  243.   {
  244.     pszOffSet = ( ( PSZ ) pErrInfoBlk ) + pErrInfoBlk->offaoffszMsg;
  245.     pszErrMsg = ( ( PSZ ) pErrInfoBlk ) + *( ( PSHORT ) pszOffSet );
  246.     if ( ( int ) hwCDFrame && ( int ) hwCDClient1 )
  247.       WinMessageBox( HWND_DESKTOP, hwCDFrame, ( PSZ ) pszErrMsg,
  248.         "SysBar/2 CD Player startup error :(", 8999,
  249.         MB_MOVEABLE | MB_ERROR | MB_CANCEL );
  250.     WinFreeErrorInfo( pErrInfoBlk );
  251.   }
  252.   WinPostMsg( hwCDClient1, WM_QUIT, ( MPARAM ) NULL, ( MPARAM ) NULL );
  253. }
  254.  
  255.  
  256. // Window invalidation functions
  257. void InvalidateTimeWindow( void )
  258. {
  259.   RECTL re = { 6, 5, iTimeWindowWidth[bLarge] - 5, iWindowHeight[bLarge] - 6 };
  260.   WinInvalidateRect( hwCDClient1, &re, FALSE );
  261. }
  262.  
  263. void InvalidateSongWindow( void )
  264. {
  265.   RECTL re = { iTimeWindowWidth[bLarge] + 1, 11, iWindowWidth[bLarge] - 6,
  266.     iWindowHeight[bLarge] - 4 };
  267.   WinInvalidateRect( hwCDClient1, &re, FALSE );
  268. }
  269.  
  270.  
  271. enum CD_Actions
  272. {
  273.   CDA_Nothing = 0,
  274.   CDA_Play,
  275.   CDA_Stop,
  276.   CDA_Pause,
  277.   CDA_Resume,
  278.   CDA_Eject,
  279.   CDA_Load,
  280.   CDA_NextTrack,
  281.   CDA_PrevTrack,
  282.   CDA_SetTrack
  283. };
  284. CD_Actions iActionToDo = 0;
  285. int iNewTrack = 0;
  286.  
  287. void DeliverCDAction( int iAction = 0 )
  288. {
  289.   iActionToDo = iAction;
  290.   DosPostEventSem( hev );
  291. }
  292.  
  293.  
  294. void AdjustButtonBitmaps( void )
  295. {
  296.   CDButtons[2]->hBitmap =
  297.     hbButtons[CurrentDrive->usStatus == CDS_Playing ? iBBmpPause : iBBmpPlay];
  298.   CDButtons[3]->hBitmap = hbButtons[CurrentDrive->usStatus == CDS_TrayOpened ?
  299.     iBBmpClose : CurrentDrive->usStatus >= CDS_Playing ? iBBmpStop : iBBmpEject ];
  300.   WinInvalidateRect( hwCDFrame, NULL, TRUE );
  301. }
  302.  
  303.  
  304. void UpdateTrackMenu( short int bForceEmpty = 0 )
  305. {
  306.   MENUITEM mi;
  307.   WinSendMsg( hmPopupMenu, MM_QUERYITEM,
  308.     MPFROM2SHORT( MNU_CD_PLAYMENU, TRUE ), MPFROMP( &mi ) );
  309.   HWND hmPlayMenu = mi.hwndSubMenu;
  310.   int n = 0;
  311.   if ( WinSendMsg( hmPlayMenu, MM_QUERYITEMCOUNT, NULL, NULL ) ) do
  312.   {
  313.     n = ( int )
  314.       WinSendMsg( hmPlayMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT( 0 ), NULL );
  315.   }
  316.   while (
  317.     WinSendMsg( hmPlayMenu, MM_DELETEITEM, MPFROM2SHORT( n, FALSE ), NULL ) );
  318.  
  319.   n = 0;
  320.   if ( ! bForceEmpty )
  321.   {
  322.     char szTrackBuffer[16];
  323.     mi.afStyle = MIS_TEXT;
  324.     mi.afAttribute = 0;
  325.     mi.hItem = 0;
  326.     mi.hwndSubMenu = NULLHANDLE;
  327.     for ( int i = 0; i < CurrentDrive->iTrackCount; i++ )
  328.     {
  329.       if ( CurrentDrive->Tracks[i].bPlayable )
  330.       {
  331.         int iTrackNumber = CurrentDrive->Tracks[i].iTrackNumber;
  332.         sprintf( szTrackBuffer, "Track %s%i", ( iTrackNumber > 9 ? "" : "~" ),
  333.           iTrackNumber );
  334.         mi.iPosition = n++;
  335.         mi.id = MNU_CD_TRACKxFIRST + i;
  336.         WinSendMsg( hmPlayMenu, MM_INSERTITEM, MPFROMP( &mi ),
  337.           MPFROMP( szTrackBuffer ) );
  338.       }
  339.     }
  340.   }
  341.   WinEnableMenuItem( hmPopupMenu, MNU_CD_PLAYMENU, n > 0 );
  342. }
  343.  
  344.  
  345. char aStack[8192];
  346. short int bContinueLoop = 1;
  347. const int iIdleTimeout = 4;
  348. const int iNormalTimeout = 2;
  349. const int iPlayTimeout = 1;
  350. int iCheckCounter = 0;
  351. int iCheckCounterTarget = iIdleTimeout;
  352.  
  353. void FAR CheckStatus( void FAR *pParam )
  354. {
  355.   HMQ hmq2 = WinCreateMsgQueue( hab, 0 );
  356.  
  357.   ULONG uPosts;
  358.   while ( bContinueLoop )
  359.   {
  360.     if ( CurrentDrive )
  361.     {
  362.       short int bInvalidateButtons = 0;
  363.       short int bInvalidateTime = 0;
  364.  
  365.       int iToDo = iActionToDo;
  366.       iActionToDo = 0;
  367.       switch ( iToDo )
  368.       {
  369.         case CDA_PrevTrack:
  370.           CurrentDrive->PrevTrack();
  371.           bInvalidateTime = 1;
  372.           break;
  373.  
  374.         case CDA_NextTrack:
  375.           CurrentDrive->NextTrack();
  376.           bInvalidateTime = 1;
  377.           break;
  378.  
  379.         case CDA_SetTrack:
  380.           CurrentDrive->SkipToTrack( iNewTrack );
  381.           bInvalidateTime = 1;
  382.           break;
  383.  
  384.         case CDA_Play:
  385.           CurrentDrive->Play();
  386.           break;
  387.  
  388.         case CDA_Resume:
  389.           CurrentDrive->Resume();
  390.           break;
  391.  
  392.         case CDA_Pause:
  393.           if ( ! CurrentDrive->Pause() )
  394.           {
  395.             bInvalidateButtons = 1;
  396.             iCheckCounterTarget = iNormalTimeout;
  397.           }
  398.           break;
  399.  
  400.         case CDA_Load:
  401.           if ( ! CurrentDrive->LoadTray() ) bInvalidateButtons = 1;
  402.           break;
  403.  
  404.         case CDA_Eject:
  405.           if ( ! CurrentDrive->EjectTray() )
  406.           {
  407.             bInvalidateButtons = 1;
  408.             iCheckCounterTarget = iIdleTimeout;
  409.             UpdateTrackMenu( 1 );
  410.           }
  411.           break;
  412.  
  413.         case CDA_Stop:
  414.           if ( ! CurrentDrive->Stop() )
  415.           {
  416.             iCheckCounterTarget = iNormalTimeout;
  417.             bInvalidateButtons = 1;
  418.           }
  419.           break;
  420.       }
  421.  
  422.       int iStatusChange = CurrentDrive->CheckStatus();
  423.  
  424.       switch ( iStatusChange )
  425.       {
  426.         case CDS_MediaInserted:
  427.           if ( bPlayInserted ) {
  428.             CurrentDrive->Shuffle(bRandomOrder);
  429.             UpdateTrackMenu();
  430.             if ( !CurrentDrive->Play() ) iCheckCounterTarget = iPlayTimeout;
  431.           }
  432.           else iCheckCounterTarget =
  433.             CurrentDrive->iTrackCount ? iNormalTimeout : iIdleTimeout;
  434.           UpdateTrackMenu();
  435.           break;
  436.  
  437.         case CDS_MediaRemoved:
  438.           iCheckCounterTarget = iIdleTimeout;
  439.           UpdateTrackMenu();
  440.           break;
  441.  
  442.         case CDS_PlayingStarted:
  443.           iCheckCounterTarget = iPlayTimeout;
  444.           break;
  445.  
  446.         case CDS_PlayingStopped:
  447.           CurrentDrive->Stop();
  448.           if( bLoopDisk ) {
  449.             CurrentDrive->Shuffle(bRandomOrder);
  450.             UpdateTrackMenu();
  451.             CurrentDrive->Play();
  452.           }
  453.           else iCheckCounterTarget = iNormalTimeout;
  454.           break;
  455.           
  456. //        case CDS_TrackChanged:
  457. //        case CDS_PositionChanged:
  458.       }
  459.  
  460.       if ( iStatusChange || iToDo )
  461.       {
  462.         if ( iStatusChange < CDS_PositionChanged ) bInvalidateButtons = 1;
  463.         else
  464.         {
  465.           bInvalidateTime = 1;
  466.           if ( iStatusChange == CDS_TrackChanged ) InvalidateSongWindow();
  467.         }
  468.       }
  469.  
  470.       if ( bInvalidateButtons ) AdjustButtonBitmaps();
  471.       if ( bInvalidateTime ) InvalidateTimeWindow();
  472.     }
  473.     DosResetEventSem( hev, &uPosts );
  474.     if ( DosWaitEventSem( hev, SEM_INDEFINITE_WAIT ) ) break;
  475.   }
  476.  
  477.   WinDestroyMsgQueue( hmq2 );
  478.   _endthread();
  479. }
  480.  
  481.  
  482. void SaveOptions( void )
  483. {
  484.   FILE *f = fopen( pszIniFile, "wt" );
  485.   if ( f )
  486.   {
  487.     SWP Swp;
  488.     if ( WinQueryWindowPos( hwCDFrame, &Swp ) )
  489.       fprintf( f, 
  490.         "[%s]\n"
  491.         "x=%i\n"
  492.         "y=%i\n"
  493.         "timemode=%i\n"
  494.         "topmost=%i\n"
  495.         "monochrome=%s\n"
  496.         "largesize=%s\n"
  497.         "cornerbind=%i\n"
  498.         "lockposition=%s\n"
  499.         "driveletter=%c\n"
  500.         "autodetectdrive=%s\n"
  501.         "autoplayinserted=%s\n"
  502.         "randomorder=%s\n"
  503.         "loopdisk=%s\n\n",
  504.         szSysBar2CD, Swp.x, Swp.y, iTimeMode, iTopmost,
  505.         pszYesNo[bMonochrome], pszYesNo[bLarge], iBindToCorner,
  506.         pszYesNo[bLockPosition], CurrentDrive->usDrive + 'A',
  507.         pszYesNo[bAutodetectDrive], pszYesNo[bPlayInserted], 
  508.         pszYesNo[bRandomOrder], pszYesNo[bLoopDisk] );
  509.     fclose( f );
  510.   }
  511. }
  512.  
  513.  
  514. MRESULT EXPENTRY SettingsDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  515. {
  516.   switch ( msg )
  517.   {
  518.     case WM_INITDLG:
  519.       WinSendDlgItemMsg( hwnd, D_Size_Small + bLarge, BM_SETCHECK,
  520.         ( MPARAM ) 1, 0 );
  521.       WinSendDlgItemMsg( hwnd, D_Display_None + iTopmost, BM_SETCHECK,
  522.         ( MPARAM ) 1, 0 );
  523.       WinSendDlgItemMsg( hwnd, D_Bind_Off + iBindToCorner, BM_SETCHECK,
  524.         ( MPARAM ) 1, 0 );
  525.       WinSendDlgItemMsg( hwnd, D_Display_Mono, BM_SETCHECK,
  526.         ( MPARAM ) bMonochrome, 0 );
  527.       WinSendDlgItemMsg( hwnd, D_Player_AutoPlay, BM_SETCHECK,
  528.         ( MPARAM ) bPlayInserted, 0 );
  529.       WinSendDlgItemMsg( hwnd, D_Lock_Position, BM_SETCHECK,
  530.         ( MPARAM ) bLockPosition, 0 );
  531.       WinSendDlgItemMsg( hwnd, D_Player_Autodetect, BM_SETCHECK,
  532.         ( MPARAM ) bAutodetectDrive, 0 );
  533.       WinSendDlgItemMsg( hwnd, D_Order_Continuous + bRandomOrder, BM_SETCHECK,
  534.         ( MPARAM ) 1, 0 );
  535.       WinSendDlgItemMsg( hwnd, D_Loop_Disc, BM_SETCHECK,
  536.         ( MPARAM ) bLoopDisk, 0 );
  537.  
  538.       {
  539.         char szDrive[3] = "A:";
  540.         int n = CDDeviceFinder( CDMap );
  541.         if ( n > 0 )
  542.         {
  543.           for ( int i = 0; i < n; i++ )
  544.           {
  545.             szDrive[0] = CDMap.usFirstLetter + i + 'A';
  546.             WinSendDlgItemMsg( hwnd, D_Player_Drive, LM_INSERTITEM,
  547.               ( MPARAM ) LIT_END, MPFROMP( szDrive ) );
  548.           }
  549.         }
  550.         szDrive[0] = CurrentDrive->usDrive + 'A';
  551.         WinSetDlgItemText( hwnd, D_Player_Drive, szDrive );
  552.       }
  553.  
  554.       WinEnableControl( hwnd, D_Player_Drive, bAutodetectDrive == 0 );
  555.       WinEnableControl( hwnd, D_Player_DriveS, bAutodetectDrive == 0 );
  556.  
  557.       break;
  558.     
  559.     case WM_COMMAND:
  560.       switch ( SHORT1FROMMP( mp1 ) )
  561.       {
  562.         case D_Player_DriveS:
  563.           {
  564.             char szDrive[3];
  565.             WinQueryDlgItemText( hwnd, D_Player_Drive, sizeof( szDrive ),
  566.               szDrive );
  567.             if ( CurrentDrive ) delete CurrentDrive;
  568.             CurrentDrive = new CDDrive( szDrive[0] );
  569.           }
  570.           break;
  571.       }
  572.       break;
  573.  
  574.     case WM_CONTROL:
  575.       if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  576.         switch ( SHORT1FROMMP( mp1 ) )
  577.       {
  578.         case D_Lock_Position:
  579.           if ( bLockPosition != ( int ) WinSendDlgItemMsg( hwnd,
  580.             D_Lock_Position, BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwCDClient1,
  581.             WM_COMMAND, ( MPARAM ) ( MNU_CD_LOCKPOSITION ), 0 );
  582.           break;
  583.         case D_Player_Autodetect:
  584.           if ( bAutodetectDrive != ( int ) WinSendDlgItemMsg( hwnd,
  585.             D_Player_Autodetect, BM_QUERYCHECK, 0, 0 ) )
  586.           {
  587.             WinPostMsg( hwCDClient1,
  588.               WM_COMMAND, ( MPARAM ) ( MNU_CD_AUTODETECT ), 0 );
  589.             WinEnableControl( hwnd, D_Player_Drive, bAutodetectDrive );
  590.             WinEnableControl( hwnd, D_Player_DriveS, bAutodetectDrive );
  591.           }
  592.           break;
  593.  
  594.         case D_Order_Continuous:
  595.         case D_Order_Random:
  596.           {
  597.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Order_Continuous,
  598.               BM_QUERYCHECKINDEX, 0, 0 );
  599.             if ( s == 0 || s == 1 ) WinPostMsg( hwCDClient1, WM_COMMAND,
  600.               ( MPARAM ) ( MNU_CD_CONTINUOUS + s ), 0 );
  601.           }
  602.           break;
  603.  
  604.         case D_Loop_Disc:
  605.           if ( bLoopDisk != ( int ) WinSendDlgItemMsg( hwnd, D_Loop_Disc, BM_QUERYCHECK, 0, 0 ) ) 
  606.               WinPostMsg( hwCDClient1, WM_COMMAND, ( MPARAM ) ( MNU_CD_LOOPDISC ), 0 );
  607.           break;
  608.  
  609.         case D_Size_Small:
  610.         case D_Size_Large:
  611.           {
  612.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Size_Small,
  613.               BM_QUERYCHECKINDEX, 0, 0 );
  614.             if ( s == 0 || s == 1 ) WinPostMsg( hwCDClient1, WM_COMMAND,
  615.               ( MPARAM ) ( MNU_CD_SMALL + s ), 0 );
  616.           }
  617.           break;
  618.         case D_Display_None:
  619.         case D_Display_OnTop:
  620.         case D_Display_Popup:
  621.         case D_Display_Popup2:
  622.           {
  623.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Display_None,
  624.               BM_QUERYCHECKINDEX, 0, 0 );
  625.             if ( ( s & 3 ) == s ) WinPostMsg( hwCDClient1, WM_COMMAND,
  626.               ( MPARAM ) ( MNU_CD_NOTOP + s ), 0 );
  627.           }
  628.           break;
  629.         case D_Bind_Off:
  630.         case D_Bind_NW:
  631.         case D_Bind_NE:
  632.         case D_Bind_SW:
  633.         case D_Bind_SE:
  634.           {
  635.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Bind_Off,
  636.               BM_QUERYCHECKINDEX, 0, 0 );
  637.             if ( s >= 0 && s <= 4 ) WinPostMsg( hwCDClient1, WM_COMMAND,
  638.               ( MPARAM ) ( MNU_CD_BIND_OFF + s ), 0 );
  639.           }
  640.           break;
  641.         case D_Display_Mono:
  642.           if ( bMonochrome != ( int ) WinSendDlgItemMsg( hwnd, D_Display_Mono,
  643.             BM_QUERYCHECK, 0, 0 ) )  WinPostMsg( hwCDClient1, WM_COMMAND,
  644.             ( MPARAM ) ( MNU_CD_MONO ), 0 );
  645.           break;
  646.         case D_Player_AutoPlay:
  647.           if ( bPlayInserted != ( int ) WinSendDlgItemMsg( hwnd,
  648.             D_Player_AutoPlay, BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwCDClient1,
  649.             WM_COMMAND, ( MPARAM ) ( MNU_CD_PLAYINSERTED ), 0 );
  650.           break;
  651.       }
  652.       break;
  653.       
  654.     default:
  655.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  656.   }
  657.   return ( MRESULT ) FALSE;
  658. }
  659.  
  660.  
  661. MRESULT EXPENTRY AboutDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  662. {
  663.   if ( msg == WM_INITDLG )
  664.   {
  665.     WinSetDlgItemText( hwnd, D_Version, SB2_Strings( iSB2S_Version ) );
  666.     WinSetDlgItemText( hwnd, D_Copyright, SB2_Strings( iSB2S_Copyright ) );
  667.     WinSetDlgItemText( hwnd, D_Email, SB2_Strings( iSB2S_Email ) );
  668.   }
  669.   return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  670. }
  671.  
  672.  
  673. // Main properties dialog window procedure -----------------------------------
  674. MRESULT EXPENTRY PropertiesDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  675. {
  676.   static ULONG ulAboutPage;
  677.   static ULONG ulSettingsPage;
  678.   static HWND hwSettingsDlg = NULL;
  679.   static HWND hwAboutDlg = NULL;
  680.  
  681.   switch ( msg )
  682.   {
  683.     case WM_INITDLG:
  684.       if ( mp2 )
  685.       {
  686.         WinSetWindowText( hwnd, "SysBar/2 CD Player - Properties" );
  687.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETNOTEBOOKCOLORS,
  688.           MPFROMLONG( SYSCLR_DIALOGBACKGROUND ),
  689.           MPFROMLONG( BKA_BACKGROUNDPAGECOLORINDEX ) );
  690.         HWND hwNotebook = WinWindowFromID( hwnd, D_Prop_Notebook );
  691.  
  692.         ulSettingsPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "General",
  693.           "General settings" );
  694.         hwSettingsDlg = WinLoadDlg( hwNotebook, hwNotebook, SettingsDlgProc,
  695.           ( HMODULE ) 0, DLG_SETTINGS, NULL );
  696.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  697.           ( MPARAM ) ulSettingsPage, ( MPARAM ) hwSettingsDlg );
  698.  
  699.         ulAboutPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "About",
  700.           "About SysBar/2 CD Player" );
  701.         hwAboutDlg = WinLoadDlg( hwNotebook, hwNotebook, AboutDlgProc,
  702.           ( HMODULE ) 0, DLG_ABOUT, NULL );
  703.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  704.           ( MPARAM ) ulAboutPage, ( MPARAM ) hwAboutDlg );
  705.  
  706.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  707.           MPFROM2SHORT ( 21, 21 ), MPFROMSHORT ( BKA_PAGEBUTTON ) );
  708.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  709.           MPFROM2SHORT ( 80, 20 ), MPFROMSHORT ( BKA_MAJORTAB ) );
  710.       }
  711.       break;
  712.  
  713.     case WM_CLOSE:
  714.       WinDestroyWindow( hwSettingsDlg );
  715.       WinDestroyWindow( hwAboutDlg );
  716.       WinPostMsg( hwCDClient1, WM_COMMAND, ( MPARAM ) MNU_CD_SAVE, 0 );
  717.     default:
  718.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  719.   }
  720.   return ( MRESULT ) FALSE;
  721. }
  722.  
  723.  
  724. HWND hwPrevWindow = HWND_DESKTOP;
  725.  
  726. void PopUpMainWindow( void )
  727. {
  728.   if ( iTopmost >= 2 ) hwPrevWindow = WinQueryWindow( hwCDFrame, QW_PREV );
  729.   WinSetWindowPos( hwCDFrame, HWND_TOP, 0L, 0L, 0L, 0L, SWP_ZORDER | SWP_SHOW );
  730.   bLastVisible = 1;
  731. }
  732.  
  733.  
  734. short int bClearIt = 0;
  735.  
  736.  
  737. MRESULT EXPENTRY CDWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  738. {
  739.   switch ( msg )
  740.   {
  741.     case WM_CREATE:
  742.       if ( bActive == 0 )
  743.       {
  744.         bActive = 1;
  745.  
  746.         HPS hps = WinGetPS( hwnd );
  747.         for ( int i = 0; i < iBBCount; i++ )
  748.           hbButtons[i] = GpiLoadBitmap( hps, NULLHANDLE, BMP_BBNULL + i, 
  749.             iBBWidth, iBBHeight );
  750.         for ( i = 0; i < iMBCount; i++ )
  751.         {
  752.           hbModes[i][0] = GpiLoadBitmap( hps, NULLHANDLE,
  753.             BMP_MBNULL + ( i << 1 ),  iMBWidth, iMBHeight );
  754.           hbModes[i][1] = GpiLoadBitmap( hps, NULLHANDLE,
  755.             BMP_MBNULL + ( i << 1 ) + 1, iMBWidth, iMBHeight );
  756.         }
  757.         WinReleasePS( hps );
  758.  
  759.         hmPopupMenu = WinLoadMenu( hwnd, NULLHANDLE, MNU_SB2_CD );
  760.         WinStartTimer( hab, hwnd, TID_USERMAX + 8, 500 );
  761.       }
  762.       break;
  763.       
  764.     case WM_COMMAND:
  765.       {
  766.         USHORT uCommand = SHORT1FROMMP( mp1 );
  767.         switch ( uCommand )
  768.         {
  769.           case MNU_CD_NOTOP:
  770.           case MNU_CD_TOPMOST:
  771.           case MNU_CD_POPUP:
  772.           case MNU_CD_POPUP2:
  773.             iTopmost = uCommand - MNU_CD_NOTOP;
  774.             break;
  775.  
  776.           case MNU_CD_BIND_OFF:
  777.           case MNU_CD_BIND_NW:
  778.           case MNU_CD_BIND_NE:
  779.           case MNU_CD_BIND_SW:
  780.           case MNU_CD_BIND_SE:
  781.             if ( ( iBindToCorner = uCommand - MNU_CD_BIND_OFF ) > 0 )
  782.             {
  783.               int x = -1;
  784.               int y = -1;
  785.               if ( iBindToCorner == 1 || iBindToCorner == 2 )
  786.                 y = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
  787.                   iWindowHeight[bLarge] + 1;
  788.               if ( iBindToCorner == 2 || iBindToCorner == 4 )
  789.                 x = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ) -
  790.                   iWindowWidth[bLarge] + 1;
  791.               WinSetWindowPos( hwCDFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE );
  792.             }
  793.             break;
  794.  
  795.           case MNU_CD_CONTINUOUS:
  796.           case MNU_CD_RANDOM:
  797.             {
  798.               bRandomOrder = (uCommand == MNU_CD_RANDOM);
  799.               CDStatuses s = CurrentDrive->usStatus;
  800.               if( s==CDS_Playing || s==CDS_Paused ) DeliverCDAction( CDA_Stop );
  801.               CurrentDrive->Shuffle( bRandomOrder );
  802.               UpdateTrackMenu();
  803.               if( s==CDS_Playing ) DeliverCDAction( CDA_Play );
  804.               break;
  805.             }
  806.           case MNU_CD_LOOPDISC:
  807.             bLoopDisk ^= 1;
  808.             break;
  809.  
  810.           case MNU_CD_SMALL:
  811.           case MNU_CD_LARGE:
  812.             bLarge = uCommand - MNU_CD_SMALL;
  813.             fat.lMaxBaselineExt = bLarge ? 16 : 13;
  814.             fat.lAveCharWidth = bLarge ? 6 : 5;
  815.             {
  816.               SWP Swp;
  817.               WinQueryWindowPos( hwCDFrame, &Swp );
  818.               WinInvalidateRect( hwCDFrame, NULL, TRUE );
  819.               WinSetWindowPos( hwCDFrame, HWND_TOP, 0, 0, iWindowWidth[bLarge],
  820.                 iWindowHeight[bLarge], SWP_SIZE | SWP_SHOW );
  821.              if ( bActive == 1 )
  822.              {
  823.                for ( int i = 0; i < 5; i++ ) CDButtons[i] = new CDButton( i );
  824.                bActive = 2;
  825.              }
  826.              else for ( int i = 0; i < 5; i++ ) CDButtons[i]->SizeWindow( i );
  827.             }
  828.             if ( iBindToCorner ) WinPostMsg( hwnd, WM_COMMAND,
  829.               ( MPARAM ) ( MNU_CD_BIND_OFF + iBindToCorner ), 0 );
  830.             break;
  831.             
  832.           case MNU_CD_LOCKPOSITION:
  833.             bLockPosition ^= 1;
  834.             break;
  835.  
  836.           case MNU_CD_MONO:
  837.             bMonochrome ^= 1;
  838.             WinInvalidateRect( hwCDFrame, NULL, TRUE );
  839.             break;
  840.             
  841.           case MNU_CD_PROPERTIES:
  842.             hwPrevWindow = HWND_TOP;
  843.             WinDlgBox( HWND_DESKTOP, hwCDFrame, PropertiesDlgProc,
  844.               hmSysBar2Dll, DLG_PROPERTIES, ( PVOID ) &DummyInit );
  845.             break;
  846.  
  847.           case MNU_CD_SAVE:
  848.             SaveOptions();
  849.             break;
  850.  
  851.           case MNU_CD_AUTODETECT:
  852.             if ( ( bAutodetectDrive ^= 1 ) == 1 )
  853.             {
  854.               USHORT usDrive =
  855.                 ( CDDeviceFinder( CDMap ) ? CDMap.usFirstLetter + 'A' : 'D' );
  856.               if ( CurrentDrive ) delete CurrentDrive;
  857.               CurrentDrive = new CDDrive( usDrive );
  858.             }
  859.             break;
  860.  
  861.           case MNU_CD_PLAYINSERTED:
  862.             bPlayInserted ^= 1;
  863.             break;
  864.  
  865.           case MNU_CD_CLOSE:
  866.             WinPostMsg( hwCDFrame, WM_CLOSE, 0, 0 );
  867.             break;
  868.  
  869.           case ID_CDTIMEBTN:
  870.             if ( CurrentDrive->iTrackCount )
  871.             {
  872.               iTimeMode = ( iTimeMode + 1 ) & 3;
  873.               InvalidateTimeWindow();
  874.             }
  875.             break;
  876.  
  877.           case ID_CDLEFTBTN:
  878.             DeliverCDAction( CDA_PrevTrack );
  879.             break;
  880.  
  881.           case ID_CDRIGHTBTN:
  882.             DeliverCDAction( CDA_NextTrack );
  883.             break;
  884.             
  885.           case ID_CDPLAYBTN:
  886.             switch ( CurrentDrive->usStatus )
  887.             {
  888.               case CDS_MediaPresent:
  889.                 DeliverCDAction( CDA_Play );
  890.                 break;
  891.  
  892.               case CDS_Paused:
  893.                 DeliverCDAction( CDA_Resume );
  894.                 break;
  895.  
  896.               case CDS_Playing:
  897.                 DeliverCDAction( CDA_Pause );
  898.                 break;
  899.             }
  900.             break;
  901.  
  902.           case ID_CDSTOPBTN:
  903.             switch ( CurrentDrive->usStatus )
  904.             {
  905.               case CDS_TrayOpened:
  906.                 DeliverCDAction( CDA_Load );
  907.                 break;
  908.  
  909.               case CDS_NoMedia:
  910.               case CDS_MediaPresent:
  911.                 DeliverCDAction( CDA_Eject );
  912.                 break;
  913.  
  914.               case CDS_Playing:
  915.               case CDS_Paused:
  916.                 DeliverCDAction( CDA_Stop );
  917.                 break;
  918.             }
  919.             break;
  920.  
  921.           default:
  922.             if ( uCommand >= MNU_CD_TRACKxFIRST &&
  923.               uCommand <= MNU_CD_TRACKxLAST )
  924.             {
  925.               iNewTrack = uCommand - MNU_CD_TRACKxFIRST;
  926.               DeliverCDAction( CDA_SetTrack );
  927.             }
  928.         }
  929.       }
  930.       break;   
  931.  
  932.     case WM_CONTROL:
  933.       {
  934.         USHORT uID = SHORT1FROMMP( mp1 );
  935.         if ( uID >= ID_CDBUTTON )
  936.         {
  937.           USHORT uCode = SHORT2FROMMP( mp1 );
  938.           switch ( uCode )
  939.           {
  940.             case BN_PAINT:
  941.               USERBUTTON *pUB = ( USERBUTTON * ) mp2;
  942.               WinPostMsg( hwCDFrame, WM_PAINTBUTTON,
  943.                 ( MPARAM ) ( uID - ID_CDBUTTON ),
  944.                 ( MPARAM ) ( pUB->fsState & BDS_HILITED ? 0 : 1 ) );
  945.               break;
  946.           }
  947.         }
  948.         
  949.       }
  950.       break;
  951.       
  952.     case WM_BUTTON1DOWN:
  953.       bLastVisible = 0;
  954.       if ( ! bLockPosition )
  955.         WinPostMsg( hwCDFrame, WM_TRACKFRAME, ( MPARAM ) TF_MOVE, 0L );
  956.       break;
  957.       
  958.     case WM_BUTTON2CLICK:
  959.       bLastVisible = 0;
  960.       WinPopupMenu( hwnd, hwnd, hmPopupMenu, SHORT1FROMMP( mp1 ), 
  961.         SHORT2FROMMP( mp1 ), 0, PU_HCONSTRAIN | PU_VCONSTRAIN |
  962.         PU_NONE | PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 );
  963.       break;
  964.       
  965.     case WM_TIMER:
  966.       if ( ( USHORT ) ( mp1 ) == TID_USERMAX + 8 )
  967.       {
  968.         if ( ++iCheckCounter >= iCheckCounterTarget )
  969.         {
  970.           DosPostEventSem( hev );
  971.           iCheckCounter = 0;
  972.         }
  973.  
  974.         short int bOnTop = iTopmost;
  975.  
  976.         if ( iTopmost >= 2 )
  977.         {
  978.           SWP swp;
  979.           WinQueryWindowPos( hwCDFrame, &swp );
  980.           POINTL ptl = { 0, 0 };
  981.           WinQueryPointerPos( HWND_DESKTOP, &ptl );
  982.           ptl.x -= swp.x;
  983.           ptl.y -= swp.y;
  984.           if ( ptl.x >= 0 && ptl.y >= 0 &&
  985.             ptl.x < iWindowWidth[bLarge] && ptl.y < iWindowHeight[bLarge] )
  986.           {
  987.             if ( ! bLastVisible ) bLastVisible = bOnTop = 1;
  988.           }
  989.           else if ( bLastVisible )
  990.           {
  991.             if ( iTopmost == 3 ) WinSetWindowPos( hwCDFrame, hwPrevWindow,
  992.               0L, 0L, 0L, 0L, SWP_ZORDER );
  993.             bLastVisible = 0;
  994.           }
  995.         }
  996.  
  997.         if ( bOnTop == 1 ) PopUpMainWindow();
  998.  
  999.       }
  1000.       break;
  1001.       
  1002.     case WM_PAINTBUTTON:
  1003.       {
  1004.         HPS hps = WinGetPS( hwnd );
  1005.         CDButtons[int ( mp1 )]->Draw( hps, ( short int ) mp2 );
  1006.         WinReleasePS( hps );
  1007.       }
  1008.       break;
  1009.       
  1010.     case WM_ERASEBACKGROUND:
  1011.       {
  1012.         bClearIt = 1;
  1013. /*      
  1014.         HPS hps = ( HPS ) mp1;
  1015.         SB2_Border( hps, 0, 0, iWindowWidth[bLarge] - 1,
  1016.           iWindowHeight[bLarge] - 1, 1, SB2c_Filler, 1 );
  1017.         SB2_Border( hps, 4, 3, iTimeWindowWidth[bLarge] - 3,
  1018.           iWindowHeight[bLarge] - 4, 0, CLR_BLACK );
  1019.         SB2_Border( hps, iTimeWindowWidth[bLarge], iStatusWindowY[bLarge],
  1020.           iWindowWidth[bLarge] - 5, iWindowHeight[bLarge] - 4, 0, CLR_BLACK );
  1021. */          
  1022.       }
  1023.       break;
  1024.       
  1025.     case WM_PAINT:
  1026.       {
  1027.         HPS hps;
  1028.         RECTL rc;
  1029.         hps = WinBeginPaint( hwnd, 0L, &rc );
  1030.  
  1031.         if ( bClearIt )
  1032.         {
  1033.           bClearIt = 0;
  1034.           SB2_Border( hps, 0, 0, iWindowWidth[bLarge] - 1,
  1035.             iWindowHeight[bLarge] - 1, 1, SB2c_Filler, 1 );
  1036.           SB2_Border( hps, 4, 3, iTimeWindowWidth[bLarge] - 3,
  1037.             iWindowHeight[bLarge] - 4, 0, CLR_BLACK );
  1038.           SB2_Border( hps, iTimeWindowWidth[bLarge], iStatusWindowY[bLarge],
  1039.             iWindowWidth[bLarge] - 5, iWindowHeight[bLarge] - 4, 0, CLR_BLACK );
  1040.           for ( int i = 0; i < iButtonCount; i++ ) CDButtons[i]->Draw( hps );
  1041.         }
  1042.  
  1043.         if ( CurrentDrive->iTrackCount )
  1044.         {
  1045.           char szBuffer[6];
  1046.           ULONG ulResultingTime = CurrentDrive->ulCurrentPosition;
  1047.  
  1048.           switch ( iTimeMode )
  1049.           {
  1050.             case 0:
  1051.               ulResultingTime = CDDrive::MSFSub( ulResultingTime,
  1052.                 CurrentDrive->Tracks[CurrentDrive->iCurrentTrack].ulStartingTime );
  1053.               break;
  1054.             case 1:
  1055.               ulResultingTime = CDDrive::MSFSub(
  1056.                 CurrentDrive->Tracks[CurrentDrive->iCurrentTrack].ulEndingTime,
  1057.                 ulResultingTime );
  1058.               break;
  1059.             case 2:
  1060.               ulResultingTime = CDDrive::MSFSub( ulResultingTime,
  1061.                 CurrentDrive->Tracks[0].ulStartingTime );
  1062.               break;
  1063.             case 3:
  1064.               ulResultingTime = CDDrive::MSFSub(
  1065.                 CurrentDrive->Tracks[CurrentDrive->iTrackCount - 1].ulEndingTime,
  1066.                 ulResultingTime );
  1067.               break;
  1068.           }
  1069.  
  1070.           sprintf( szBuffer, "%02i:%02i",
  1071.             ( ulResultingTime >> 16 ) & 255, ( ulResultingTime >> 8 ) & 255 );
  1072.           SB2_LargeDigits( hps, 8, 6, szBuffer, bMonochrome, bLarge );
  1073.           
  1074.           sprintf( szBuffer, "%02i",
  1075.             CurrentDrive->Tracks[CurrentDrive->iCurrentTrack].iTrackNumber );
  1076.           SB2_SmallDigits( hps, iTrackX[bLarge], ( iWindowHeight[bLarge] >>
  1077.             1 ) + 1 + bLarge, szBuffer, bMonochrome, bLarge );
  1078.             
  1079.           POINTL pt4[4] =
  1080.           {
  1081.             { iTrackX[bLarge] + ( bLarge << 1 ) + 3, 6 + ( bLarge << 1 ) },
  1082.             { iTrackX[bLarge] + ( bLarge << 1 ) + 2 + iMBWidth,
  1083.               5 + iMBHeight + ( bLarge << 1 ) },
  1084.             { 0, 0 }, { iMBWidth, iMBHeight }
  1085.           };
  1086.           int iStatus = 0;
  1087.           GpiWCBitBlt( hps, hbModes[CurrentDrive->usStatus -
  1088.             CDS_MediaPresent][bMonochrome], 4L, pt4, ROP_SRCCOPY, BBO_IGNORE );
  1089.         }
  1090.  
  1091.         SB2_Border( hps, iTimeWindowWidth[bLarge], iStatusWindowY[bLarge],
  1092.           iWindowWidth[bLarge] - 5, iWindowHeight[bLarge] - 4, 0, CLR_BLACK );
  1093.         fat.usCodePage = GpiQueryCp( hps );
  1094.         GpiCreateLogFont( hps, NULL, 200L, &fat );
  1095.         GpiSetCharSet( hps, 200L );
  1096.         CHARBUNDLE cb;
  1097.         cb.lColor = bMonochrome ? CLR_WHITE : CLR_GREEN;
  1098.         cb.usTextAlign = TA_LEFT | TA_BASE;
  1099.         GpiSetAttrs( hps, PRIM_CHAR, CBB_COLOR | CBB_TEXT_ALIGN, 0, &cb );
  1100.  
  1101.         POINTL pt;
  1102.         pt.x = iTimeWindowWidth[bLarge] + 2;
  1103.         pt.y = iStatusWindowY[bLarge] + 3 + bLarge;
  1104.         RECTL rc1;
  1105.         rc1.xLeft = iTimeWindowWidth[bLarge] + 2;
  1106.         rc1.yBottom = iStatusWindowY[bLarge] + 1;
  1107.         rc1.xRight = iWindowWidth[bLarge] - 6;
  1108.         rc1.yTop = iWindowHeight[bLarge] - 5;
  1109.         ULONG uOptions = CHS_CLIP;
  1110.         char *pS =
  1111.           CurrentDrive->usStatus > CDS_NoMedia && ! CurrentDrive->iTrackCount ?
  1112.           szCDM_NonAudio : pszCDMessages[CurrentDrive->usStatus];
  1113.         if ( CurrentDrive->usStatus == CDS_Playing )
  1114.         {
  1115.           char szBuffer[16];
  1116.           sprintf( szBuffer, "%s %i", pS,
  1117.             CurrentDrive->Tracks[CurrentDrive->iCurrentTrack].iTrackNumber );
  1118.           pS = szBuffer;
  1119.         }
  1120.         GpiCharStringPosAt( hps, &pt, &rc1, uOptions, strlen( pS ), pS, NULL );
  1121.         GpiDeleteSetId( hps, 200L );
  1122.  
  1123.         WinEndPaint( hps );
  1124.       }
  1125.       break;
  1126.       
  1127.     case WM_CLOSE:
  1128.       SaveOptions();
  1129.       CurrentDrive->Pause();
  1130.       CurrentDrive->Close();
  1131.       WinPostMsg( hwnd, WM_QUIT, 0, 0 );
  1132.       break;      
  1133.       
  1134.     case WM_DESTROY:
  1135.       if ( bActive )
  1136.       {
  1137.         bContinueLoop = 0;
  1138.         bActive = 0;
  1139.         WinStopTimer( hab, hwnd, TID_USERMAX + 8 );
  1140.         for ( int i = 0; i < iBBCount; i++ )
  1141.           GpiDeleteBitmap( hbButtons[i] );
  1142.         for ( i = 0; i < iMBCount; i++ )
  1143.         {
  1144.           GpiDeleteBitmap( hbModes[i][0] );
  1145.           GpiDeleteBitmap( hbModes[i][1] );
  1146.         }
  1147.       }
  1148.       break;
  1149.  
  1150.     case WM_MOUSEMOVE:
  1151.       if ( iTopmost >= 2 && ! bLastVisible ) PopUpMainWindow();
  1152.  
  1153.     default:
  1154.       return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  1155.   }
  1156.   return ( MRESULT ) FALSE;
  1157. }
  1158.  
  1159.  
  1160. int main( int argc, char *argv[] )
  1161. {
  1162.   HMQ hmq;
  1163.   QMSG qmsg;
  1164.   char szClassName[] = "SysBar2CDClass";
  1165.  
  1166.   fat.usRecordLength = sizeof ( FATTRS );
  1167.   fat.fsSelection = 0;
  1168.   fat.lMatch = 0;
  1169.   fat.idRegistry = 0;
  1170.   fat.usCodePage = 0;
  1171.   fat.fsType = 0;
  1172.   fat.fsFontUse = FATTR_FONTUSE_NOMIX;
  1173.   strcpy( fat.szFacename, "Helv" );
  1174.  
  1175.   if ( ( hab = WinInitialize( 0 ) ) == 0L ) AbortStartup();
  1176.   if ( ( hmq = WinCreateMsgQueue( hab, 0 ) ) == 0L ) AbortStartup();
  1177.  
  1178.   hmSysBar2Dll = SB2_Init();
  1179.  
  1180.   {
  1181.     TIB *tib;
  1182.     PIB *pib;
  1183.     DosGetInfoBlocks( &tib, &pib );
  1184.     char szSemNameBuffer[48];
  1185.  
  1186.     sprintf( szSemNameBuffer, "%s%i", szSemName, pib->pib_ulpid );
  1187.  
  1188.     if ( DosCreateEventSem( szSemNameBuffer, &hev, 0, 0 ) ) AbortStartup();
  1189.     _beginthread( CheckStatus, aStack, sizeof ( aStack ), NULL );
  1190.   }
  1191.  
  1192.   if ( ! WinRegisterClass( hab, ( PSZ ) szClassName, 
  1193.     ( PFNWP ) CDWinProc, 0L, 0 ) ) AbortStartup();
  1194.  
  1195.   pszIniFile = new char[strlen( argv[0] ) + 1];
  1196.   SB2_CfgFilename( pszIniFile, argv[0] );
  1197.  
  1198.   ULONG ulWinStyle = FCF_AUTOICON | FCF_ICON | FCF_NOBYTEALIGN | FCF_TASKLIST;
  1199.     
  1200.   if ( ( hwCDFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWinStyle,
  1201.     szClassName, 0, 0, NULLHANDLE, ICO_MAIN, &hwCDClient1 ) ) == 0L )
  1202.     AbortStartup();
  1203.  
  1204.   WinSetWindowText( hwCDFrame, "SysBar/2 CD Player" );
  1205.  
  1206.   srand( hwCDFrame );
  1207.  
  1208.   {
  1209.     int x = 0, y = 0;
  1210.     IniFile *pCfg = new IniFile( pszIniFile );
  1211.  
  1212.     USHORT usDrive =
  1213.       ( CDDeviceFinder( CDMap ) ? CDMap.usFirstLetter + 'A' : 'D' );
  1214.  
  1215.     if ( pCfg && ( *pCfg )() )
  1216.     {
  1217.       x = atoi2( pCfg->Get( szSysBar2CD, "x" ) );
  1218.       y = atoi2( pCfg->Get( szSysBar2CD, "y" ) );
  1219.       iTimeMode = atoi2( pCfg->Get( szSysBar2CD, "timemode" ) ) & 3;
  1220.       iTopmost = atoi2( pCfg->Get( szSysBar2CD, "topmost" ) ) & 3;
  1221.       bMonochrome = 
  1222.         ( strcmp2( pCfg->Get( szSysBar2CD, "monochrome" ), pszYesNo[1] ) == 0 );
  1223.       bLarge = 
  1224.         ( strcmp2( pCfg->Get( szSysBar2CD, "largesize" ), pszYesNo[1] ) == 0 );
  1225.       iBindToCorner = atoi2( pCfg->Get( szSysBar2CD, "cornerbind" ) );
  1226.       if ( iBindToCorner > 4 || iBindToCorner < 0 ) iBindToCorner = 0;
  1227.       bLockPosition = ( strcmp2(
  1228.         pCfg->Get( szSysBar2CD, "lockposition" ), pszYesNo[1] ) == 0 );
  1229.       bPlayInserted = ( strcmp2(
  1230.         pCfg->Get( szSysBar2CD, "autoplayinserted" ), pszYesNo[1] ) == 0 );
  1231.       bRandomOrder = ( strcmp2(
  1232.         pCfg->Get( szSysBar2CD, "randomorder" ), pszYesNo[1] ) == 0 );
  1233.       bLoopDisk = ( strcmp2(
  1234.         pCfg->Get( szSysBar2CD, "loopdisk" ), pszYesNo[1] ) == 0 );
  1235.  
  1236.       if ( ( bAutodetectDrive = ( strcmp2( pCfg->Get( szSysBar2CD,
  1237.         "autodetectdrive" ), pszYesNo[1] ) == 0 ) ) == 0 )
  1238.       {
  1239.         char *szDrive = pCfg->Get( szSysBar2CD, "driveletter" );
  1240.         if ( szDrive && *szDrive ) usDrive = *szDrive;
  1241.       }
  1242.     }
  1243.     delete pCfg;
  1244.     CurrentDrive = new CDDrive( usDrive );
  1245.  
  1246.     if ( ! WinSetWindowPos( hwCDFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE ) )
  1247.       AbortStartup();
  1248.     else
  1249.     {
  1250.       WinPostMsg( hwCDFrame, WM_COMMAND,
  1251.         ( MPARAM ) ( MNU_CD_BIND_OFF + iBindToCorner ), 0L );
  1252.       WinPostMsg( hwCDFrame, WM_COMMAND,
  1253.         ( MPARAM ) ( MNU_CD_SMALL + bLarge ), 0L );
  1254.     }
  1255.   }
  1256.  
  1257.   while ( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) ) WinDispatchMsg( hab, &qmsg );
  1258.   
  1259.   SB2_Over();
  1260.  
  1261.   WinDestroyWindow( hwCDFrame );
  1262.  
  1263.   DosCloseEventSem( hev );
  1264.  
  1265.   delete pszIniFile;
  1266.  
  1267.   WinDestroyMsgQueue( hmq );
  1268.   WinTerminate( hab );
  1269.  
  1270.   return 0;
  1271. }
  1272.  
  1273.