xtractor.c
上传用户:xmgzy123
上传日期:2007-01-07
资源大小:373k
文件大小:43k
源码类别:

SCSI/ASPI

开发平台:

WINDOWS

  1. /*
  2.  * xtractor.c - Copyright (C) 1999,2000 Jay A. Key
  3.  *
  4.  * Main file for CD-DA X-Tractor, a CD audio extaction tool for 32-bit
  5.  * windows platforms.
  6.  *
  7.  **********************************************************************
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22.  *
  23.  */
  24. #include <windows.h>
  25. #include <wingdi.h>
  26. #include <commctrl.h>
  27. #include <math.h>
  28. #include "akrip/akrip32.h"
  29. #include "resources.h"
  30. #include "trackwnd.h"
  31. #include "globals.h"
  32. #include "id3.h"
  33. #include "riptracks.h"
  34. #include "statusbar.h"
  35. #include "cddbdlg.h"
  36. #include "config.h"
  37. #if (__IBMC__)                         /* BWT (20000127)                   */
  38. WINCOMMCTRLAPI void WINAPI InitCommonControls(void);   /* BWT (20000127)   */
  39. #endif                                 /* BWT (20000127)                   */
  40. void logMessage( int which, UINT uMsg, WPARAM wParam, LPARAM lParam );
  41. LRESULT CALLBACK Edit0Proc( HWND, UINT, WPARAM, LPARAM );
  42. LRESULT CALLBACK Edit1Proc( HWND, UINT, WPARAM, LPARAM );
  43. LRESULT CALLBACK Edit2Proc( HWND, UINT, WPARAM, LPARAM );
  44. LRESULT CALLBACK akripWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  45. HWND createToolbar( HWND hWnd, HINSTANCE hInst );
  46. HWND createHeader( HWND hWnd, HINSTANCE hInst );
  47. void doPaint( HWND hWnd );
  48. void ComputeHeaderPos( HWND hParent );
  49. void handleToolbarNotify( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  50. int WindowHeight( HWND hWnd );
  51. void RefreshTrackList( void );
  52. int DoConfig( HWND hParent, HINSTANCE hInst, UINT uiStartPage );
  53. void InitAKRip( void );
  54. void DeinitAKRip( void );
  55. void MSB2DWORD( DWORD *d, BYTE *b );
  56. int readRegSZ( HKEY hKey, LPCTSTR lpszValue, LPSTR lpszData, DWORD dwDataLen );
  57. int readRegDWORD( HKEY hKey, LPCTSTR lpszValue, DWORD *pdw );
  58. int doTrackContextMenu( HWND hParent, HWND hChild, LPARAM lParam );
  59. BOOL InitGauge( HINSTANCE hInst );
  60. BOOL RipTrackDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  61. BOOL loadBladeEnc( void );
  62. void disableAutoPlay( void );
  63. void restoreAutoPlay( void );
  64. void GetEditItemText( int iCtlId, HWND hCtl );
  65. BOOL CALLBACK ID3InfoDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  66. void SetEditItemText( int iCtlId, char *s );
  67. void CheckEnableID3MenuItem( HWND hWnd );
  68. void CheckEnableCDDBMenuItem( HWND hWnd );
  69. void CheckEnableHiColorMenuItem( HWND hWnd );
  70. BOOL CALLBACK AboutDialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  71. void InitBmpPanel( void );
  72. void DynamicAboutDialog( HWND hParent );
  73. void ShowHelpFile( HWND hWnd, int topic );
  74. void DiffTimeToString( double d, char *buf );
  75. static void GetLineFromBuf( char *tgt, char **src, int len );
  76. void DoCDDBQuery( HWND hWnd );
  77. void SetTrackText( char *buf, int i );
  78. DWORD DoCDDBQueryThread( LPVOID lpParam );
  79. HCDROM findAvailableCD( void );
  80. BOOL RipTrackSegment( HWND hParent, HWND hTrckWnd );
  81. BOOL CALLBACK CDPropertiesDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  82. void dbprintf( char *fmt, ... );
  83. DWORD GetDllVersion( LPCTSTR lpszDllName );
  84. LRESULT CALLBACK SubToolbarProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  85.  LPARAM lParam );
  86. HIMAGELIST CreateToolbarImageList( HWND hWnd, HINSTANCE hInst, int idResource );
  87. int AddToolbarImages( HINSTANCE hInst, HWND hWnd, BOOL bSysColorChange, BOOL bToggleHiColor );
  88. BOOL DisplayIsHiColor( void );
  89. char szClassName[] = "xtractor";
  90. static int  iStatusHeight = 0;
  91. static int  iToolbarHeight;
  92. HWND hStatus = NULL;
  93. HWND hTrackWnd = NULL;
  94. static HWND hToolbar = NULL;
  95. static HWND hEditArtist, hEditAlbum;
  96. static HIMAGELIST hImgLists[3] = { NULL, NULL, NULL };
  97. static WNDPROC lpfnToolbarProc = NULL;
  98. static char regKeyName[] = "SOFTWARE\AKSoft\X-Tractor";
  99. static unsigned long ulOldAutorun = (unsigned long)0x95;
  100. static char szOldAutoPlay[256] = "Play";
  101. static char regAutoPlay[] = "Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
  102. static char regAutoAudioCD[] = "AudioCD\Shell";
  103. /*
  104.  * Global variables
  105.  */
  106. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine,
  107.     int nCmdShow )
  108. {
  109.   WNDCLASSEX wc;
  110.   HWND hWnd;
  111.   MSG msg;
  112.   RECT rc;
  113.   static int aStatusWidths[3] = {40, 290,-1};
  114.   INITCOMMONCONTROLSEX ic;
  115.   ic.dwSize = sizeof(ic);
  116.   ic.dwICC = ICC_WIN95_CLASSES;
  117.   InitCommonControlsEx(&ic);
  118.   ghInstance = hInst;
  119.   hPrevInst = hPrevInst;
  120.   lpszCmdLine = lpszCmdLine;
  121.   InitTrackWnd( hInst );
  122.   InitAKRip( );
  123.   InitGauge( hInst );
  124.   bMP3 = loadBladeEnc();
  125.   InitBmpPanel();
  126.   ZeroMemory( &wc, sizeof(wc) );
  127.   wc.cbSize        = sizeof(WNDCLASSEX);
  128.   wc.style         = CS_HREDRAW | CS_VREDRAW;
  129.   wc.lpfnWndProc   = (WNDPROC)akripWndProc;
  130.   wc.hInstance     = hInst;
  131.   wc.hIcon         = LoadIcon( hInst, "ALTRIP3" );
  132.   wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  133.   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  134.   wc.lpszClassName = szClassName;
  135.   wc.lpszMenuName  = "akripMenu";
  136.   wc.hIconSm       = LoadIcon( hInst, "ALTRIP3" );
  137.   if ( !RegisterClassEx( &wc ) )
  138.     return FALSE;
  139.   hWnd = CreateWindowEx( WS_EX_APPWINDOW, szClassName, "CD-DA X-Tractor",
  140.  WS_OVERLAPPEDWINDOW,
  141.  CW_USEDEFAULT, CW_USEDEFAULT,
  142.  540, 400,
  143.  NULL, NULL, hInst, NULL );
  144.   if ( !hWnd )
  145.     return FALSE;
  146.   hToolbar = createToolbar( hWnd, hInst );
  147.   iToolbarHeight = WindowHeight( hToolbar );
  148.   hStatus = CreateStatusWindow( WS_VISIBLE | WS_CHILD | SBARS_SIZEGRIP,
  149. "", hWnd, IDM_STATUSBAR );
  150.   SendMessage( hStatus, SB_SETPARTS, 3, (LPARAM)aStatusWidths );
  151.   iStatusHeight = WindowHeight( hStatus );
  152.   GetClientRect( hWnd, &rc );
  153.   rc.top += iToolbarHeight;
  154.   rc.bottom -= iStatusHeight;
  155.   hTrackWnd = createTrackWnd( hWnd, hInst, IDM_TRACKWND, &rc );
  156.   if ( bAutoTOC )
  157.     {
  158.       SendMessage( hWnd, WM_COMMAND, MAKEWPARAM( IDM_REFRESH, BN_CLICKED ), 0L );
  159.       if ( bAutoCheck )
  160. SendMessage( hTrackWnd, WM_CHECKTRACK, (WPARAM)ALLTRACKS, (LPARAM)TRUE );
  161.     }
  162.   ShowWindow( hWnd, nCmdShow );
  163.   UpdateWindow( hWnd );
  164.   disableAutoPlay();
  165.   while( GetMessage( &msg, NULL, 0, 0 ) )
  166.     {
  167.       TranslateMessage( &msg );
  168.       DispatchMessage( &msg );
  169.     }
  170.   restoreAutoPlay();
  171.   if ( hImgLists[0] ) ImageList_Destroy( hImgLists[0] );
  172.   if ( hImgLists[1] ) ImageList_Destroy( hImgLists[1] );
  173.   if ( hImgLists[2] ) ImageList_Destroy( hImgLists[2] );
  174.   return msg.wParam;
  175. }
  176. LRESULT CALLBACK akripWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  177. {
  178.   RECT rc;
  179.   switch( uMsg )
  180.     {
  181.     case WM_CREATE:
  182.       CheckEnableID3MenuItem( hWnd );
  183.       CheckEnableCDDBMenuItem( hWnd );
  184.       if ( GetDllVersion( "comctl32.dll" ) < MAKELONG(4,71) )
  185. {
  186.   // disallow switching between 8- and 24-bit bitmaps in the toolbar
  187.   bHiColor = FALSE;
  188.   EnableMenuItem( GetMenu( hWnd ), IDM_HICOLOR, MF_BYCOMMAND | MF_GRAYED );
  189. }
  190.       CheckEnableHiColorMenuItem( hWnd );
  191.     break;
  192.     case WM_COMMAND:
  193.       switch( LOWORD( wParam ) )
  194. {
  195. case IDM_EXIT:
  196.   DestroyWindow( hWnd );
  197.   break;
  198. case IDM_REFRESH:
  199.   if ( !bInCDDBQuery )
  200.     {
  201.       RefreshTrackList( );
  202.       asSetID3Info( ID3_ERASE, NULL, 0 );
  203.       SetEditItemText( IDE_ARTIST, "" );
  204.       SetEditItemText( IDE_ALBUM, "" );
  205.       if ( bAutoCheck )
  206. SendMessage( hTrackWnd, WM_CHECKTRACK, (WPARAM)ALLTRACKS, (LPARAM)TRUE );
  207.       if ( bCDDB )
  208. DoCDDBQuery( hWnd );
  209.     }
  210.   break;
  211. case IDM_RIP:
  212.   DialogBoxParam( ghInstance, "RipTrackDialog", hWnd, (DLGPROC)RipTrackDlgProc, (LPARAM)hTrackWnd );
  213.   break;
  214. case IDM_ID3:
  215. case IDM_ID3TAGEDIT:
  216.   DialogBox( ghInstance, "ID3InfoDialog", hWnd, (DLGPROC)ID3InfoDlgProc );
  217.   break;
  218. case IDM_CDPARMS:
  219.   DialogBox( ghInstance, "CDPropertiesDialog", hWnd, (DLGPROC)CDPropertiesDlgProc );
  220.   break;
  221. case IDM_CDSETTINGS:
  222. case IDM_OPTIONS:
  223.   DoConfig( hWnd, ghInstance, 0 );
  224.   break;
  225. case IDM_DIRSETTINGS:
  226.   DoConfig( hWnd, ghInstance, 1 );
  227.   break;
  228. case IDM_MP3SETTINGS:
  229.   DoConfig( hWnd, ghInstance, 2 );
  230.   break;
  231. case IDM_CDDBSETTINGS:
  232.   DoConfig( hWnd, ghInstance, 3 );
  233.   break;
  234. case IDM_CHECKALL:
  235.   SendMessage( hTrackWnd, WM_CHECKTRACK, ALLTRACKS, (LPARAM)TRUE );
  236.   break;
  237. case IDM_INVERT:
  238.   SendMessage( hTrackWnd, WM_INVERTCHECK, ALLTRACKS, 0L );
  239.   break;
  240. case IDM_RENAME:
  241.   SendMessage( hTrackWnd, WM_RENSELTRACK, 0, 0L );
  242.   break;
  243. case IDE_ARTIST:
  244. case IDE_ALBUM:
  245.   if ( (int)HIWORD( wParam ) == EN_CHANGE )
  246.     GetEditItemText( (int)LOWORD( wParam ), (HWND)lParam );
  247.   break;
  248. case IDM_ENABLEID3:
  249.   bID3 = !bID3;
  250.   CheckEnableID3MenuItem( hWnd );
  251.   break;
  252. case IDM_ENABLECDDB:
  253.   bCDDB = !bCDDB;
  254.   CheckEnableCDDBMenuItem( hWnd );
  255.   break;
  256. case IDM_HICOLOR:
  257.   bHiColor = !bHiColor;
  258.   CheckEnableHiColorMenuItem( hWnd );
  259.   AddToolbarImages( ghInstance, hToolbar, FALSE, TRUE );
  260.   break;
  261. case IDM_ABOUT:
  262.   DynamicAboutDialog( hWnd );
  263.   break;
  264. case IDM_HELPTOPICS:
  265.   ShowHelpFile( hWnd, IDM_HELPTOPICS );
  266.   break;
  267. case IDM_RIPSEGMENT:
  268.   RipTrackSegment( hWnd, hTrackWnd );
  269.   break;
  270. }
  271.       break;
  272.     case WM_DESTROY:
  273.       DeinitAKRip( );
  274.       PostQuitMessage( 0 );
  275.       break;
  276.     case WM_NOTIFY:
  277.       switch( wParam )
  278. {
  279. case IDM_TOOLBAR:
  280.   handleToolbarNotify( hWnd, uMsg, wParam, lParam );
  281.   break;
  282. }
  283.       break;
  284.     case WM_SYSCOLORCHANGE:
  285.       SendMessage( hToolbar, uMsg, wParam, lParam );
  286.       SendMessage( hTrackWnd, uMsg, wParam, lParam );
  287.       break;
  288.     case WM_PAINT:
  289.       doPaint( hWnd );
  290.       break;
  291.     case WM_SIZE:
  292.       SendMessage( hToolbar, TB_AUTOSIZE, 0, 0L );
  293.       GetClientRect( hWnd, &rc );
  294.       MoveWindow( hStatus, 0, rc.bottom - iStatusHeight, rc.right - rc.left, rc.bottom, TRUE );
  295.       rc.top += iToolbarHeight;
  296.       rc.bottom -= iStatusHeight;
  297.       MoveWindow( hTrackWnd, 0, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE );
  298.       break;
  299.     default:
  300.       return DefWindowProc( hWnd, uMsg, wParam, lParam );
  301.     }
  302.   return 0L;
  303. }
  304. /*
  305.  * Subclass wndproc for Toolbar.  Handles the WM_SYSCOLORCHANGE and
  306.  * also the tooltip messages
  307.  */
  308. #define WM_SETSUBCLASSPROC  (WM_USER+999)
  309. LRESULT CALLBACK SubToolbarProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  310.  LPARAM lParam )
  311. {
  312.   LPTOOLTIPTEXT lpt = (LPTOOLTIPTEXT)lParam;
  313.   if ( uMsg == WM_SETSUBCLASSPROC )
  314.     {
  315.       lpfnToolbarProc = (WNDPROC)GetWindowLong( hWnd, GWL_WNDPROC );
  316.       SetWindowLong( hWnd, GWL_WNDPROC, (LONG)SubToolbarProc );
  317.       return 0L;
  318.     }
  319.   switch( uMsg )
  320.     {
  321.     case WM_SYSCOLORCHANGE:
  322.       AddToolbarImages( ghInstance, hWnd, TRUE, FALSE );
  323.       return CallWindowProc( lpfnToolbarProc, hWnd, uMsg, wParam, lParam );
  324.     case WM_NOTIFY:
  325.       if ( lpt->hdr.code == TTN_GETDISPINFOA || lpt->hdr.code == TTN_GETDISPINFOW )
  326. {
  327.   lpt->hinst = ghInstance;
  328.   lpt->lpszText = MAKEINTRESOURCE(lpt->hdr.idFrom);
  329.   return 0L;
  330. }
  331.       break;
  332.     default:
  333.       break;
  334.     }
  335.   return CallWindowProc( lpfnToolbarProc, hWnd, uMsg, wParam, lParam );
  336. }
  337. HIMAGELIST CreateToolbarImageList( HWND hWnd, HINSTANCE hInst, int idResource )
  338. {
  339.   HIMAGELIST retVal;
  340.   HBITMAP hBmp;
  341.   retVal = ImageList_Create( 50, 50, ILC_COLOR24 | ILC_MASK, 5, 0 );
  342.   hBmp = LoadBitmap( hInst, MAKEINTRESOURCE(idResource) );
  343.   ImageList_AddMasked( retVal, hBmp, RGB(192,192,192) );
  344.   DeleteObject( hBmp );
  345.   return retVal;
  346. }
  347. int AddToolbarImages( HINSTANCE hInst, HWND hWnd, BOOL bSysColorChange,
  348.       BOOL bToggleHiColor )
  349. {
  350.   TBADDBITMAP tbBitmaps;
  351.   HIMAGELIST hOldImageList[3] = { NULL, NULL, NULL };
  352.   int iBmp, iHotBmp, iOldBmp;
  353.   if ( bHiColor )
  354.     {
  355.       iBmp = idToolbar24Bmp;
  356.       iOldBmp = idToolbarBmp;
  357.       iHotBmp = idToolbarHot24Bmp;
  358.     }
  359.   else
  360.     {
  361.       iBmp = idToolbarBmp;
  362.       iOldBmp = idToolbar24Bmp;
  363.       iHotBmp = idToolbarHotBmp;
  364.     }
  365.   // check if we can use the flat toolbar with "hot" buttons
  366.   if ( GetDllVersion( "comctl32.dll" ) < MAKELONG(4,71) )
  367.     {
  368.       /*
  369.        * Only add the bitmap on initial creation when using older version
  370.        * of comctl32.dll.  Otherwise we ignore the call.
  371.        */
  372.       if ( !bSysColorChange && !bToggleHiColor )
  373. {
  374.   // use old style
  375.   tbBitmaps.hInst = NULL;
  376.   tbBitmaps.nID = (UINT)LoadBitmap( hInst, MAKEINTRESOURCE( iBmp ) );
  377.   SendMessage( hWnd, TB_ADDBITMAP, 5, (LPARAM)&tbBitmaps );
  378. }
  379.     }
  380.   else
  381.     {
  382.       /*
  383.        * We'll actually change imagelists for v4.71+ of comctl32.dll.
  384.        */
  385.       if ( bSysColorChange || bToggleHiColor )
  386. {
  387.   hOldImageList[0] = hImgLists[0];
  388.   hOldImageList[1] = hImgLists[1];
  389.   hOldImageList[2] = hImgLists[2];
  390. }
  391.       // create image lists
  392.       hImgLists[0] = CreateToolbarImageList( hWnd, hInst, iBmp );
  393.       SendMessage( hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImgLists[0] );
  394. #if _CONFIG_FLAT_TOOLBAR
  395.       hImgLists[1] = CreateToolbarImageList( hWnd, hInst, iHotBmp );
  396.       SendMessage( hWnd, TB_SETHOTIMAGELIST, 0, (LPARAM)hImgLists[1] );
  397. #endif
  398.     }
  399.   if ( hOldImageList[0] ) ImageList_Destroy( hOldImageList[0] );
  400.   if ( hOldImageList[1] ) ImageList_Destroy( hOldImageList[1] );
  401.   if ( hOldImageList[2] ) ImageList_Destroy( hOldImageList[2] );
  402.   return 0;
  403. }
  404. /*
  405.  * Creates the toolbar, loads bitmap resources, etc.  InitCommonControls()
  406.  * must be called prior to calling this function
  407.  */
  408. HWND createToolbar( HWND hWnd, HINSTANCE hInst )
  409. {
  410.   HWND hRet;
  411.   TBBUTTON tb[4];
  412.   int idx = 0;
  413.   RECT rc;
  414.   DWORD dwToolbarStyle = WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS;
  415.   memset( tb, 0, sizeof(TBBUTTON[4]) );
  416.   tb[idx].iBitmap = 0;
  417.   tb[idx].idCommand = IDM_REFRESH;
  418.   tb[idx].fsState = TBSTATE_ENABLED;
  419.   tb[idx].fsStyle = TBSTYLE_BUTTON;
  420.   tb[idx].dwData = 0;
  421.   tb[idx++].iString = -1;
  422.   tb[idx].iBitmap = 2;
  423.   tb[idx].idCommand = IDM_RIP;
  424.   tb[idx].fsState = TBSTATE_ENABLED;
  425.   tb[idx].fsStyle = TBSTYLE_BUTTON;
  426.   tb[idx].dwData = 0;
  427.   tb[idx++].iString = -1;
  428. #if 0
  429.   tb[idx].iBitmap = 1;
  430.   tb[idx].idCommand = IDM_MP3;
  431.   tb[idx].fsState = TBSTATE_ENABLED;
  432.   tb[idx].fsStyle = TBSTYLE_CHECK;
  433.   tb[idx].dwData = 0;
  434.   tb[idx++].iString = -1;
  435. #endif
  436.   tb[idx].iBitmap = 3;
  437.   tb[idx].idCommand = IDM_OPTIONS;
  438.   tb[idx].fsState = TBSTATE_ENABLED;
  439.   tb[idx].fsStyle = TBSTYLE_BUTTON;
  440.   tb[idx].dwData = 0;
  441.   tb[idx++].iString = -1;
  442.   tb[idx].iBitmap = 4;
  443.   tb[idx].idCommand = IDM_ID3;
  444.   tb[idx].fsState = TBSTATE_ENABLED;
  445.   tb[idx].fsStyle = TBSTYLE_BUTTON;
  446.   tb[idx].dwData = 0;
  447.   tb[idx++].iString = -1;
  448.   hRet = CreateWindowEx( WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, "",
  449.  dwToolbarStyle,
  450.  0, 0, 100, 64,
  451.  hWnd, (HMENU)IDM_TOOLBAR, hInst, NULL );
  452. #if _CONFIG_FLAT_TOOLBAR
  453.   dwToolbarStyle = (DWORD)SendMessage( hRet, TB_GETSTYLE, 0, 0L );
  454.   dwToolbarStyle |= TBSTYLE_FLAT;
  455.   SendMessage( hRet, TB_SETSTYLE, 0, (LPARAM)dwToolbarStyle );
  456. #endif
  457.   SendMessage( hRet, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L );
  458.   SendMessage( hRet, TB_SETBITMAPSIZE, 0, MAKELONG( 50, 46 ) );
  459.   SendMessage( hRet, TB_SETBUTTONSIZE, 0, MAKELONG( 58, 53 ) );
  460.   SendMessage( hRet, TB_AUTOSIZE, 0, 0L );
  461.   AddToolbarImages( hInst, hRet, FALSE, FALSE );
  462.   SendMessage( hRet, TB_ADDBUTTONS, idx, (LPARAM)&tb );
  463.   SubToolbarProc( hRet, WM_SETSUBCLASSPROC, 0, 0L );
  464.   SendMessage( hRet, TB_GETITEMRECT, (WPARAM)(idx-1), (LPARAM)&rc );
  465.   CreateWindowEx( 0L, "STATIC", "Artist: ",
  466.   SS_RIGHT | WS_CHILD | WS_VISIBLE,
  467.   rc.right + 10, rc.top + 6, 60, 20, hRet,
  468.   (HMENU)NULL, hInst, NULL );
  469.   CreateWindowEx( 0L, "STATIC", "Album: ",
  470.   SS_RIGHT | WS_CHILD | WS_VISIBLE,
  471.   rc.right + 10, rc.top + 32, 60, 20, hRet,
  472.   (HMENU)NULL, hInst, NULL );
  473.   hEditArtist = CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT", "",
  474.   ES_LEFT | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
  475.   | WS_BORDER | WS_TABSTOP | WS_GROUP ,
  476.   rc.right + 72, rc.top + 2, 210, 24, hRet,
  477.   (HMENU)IDE_ARTIST, hInst, NULL );
  478.   hEditAlbum = CreateWindowEx( WS_EX_CLIENTEDGE, "EDIT", "",
  479.   ES_LEFT | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
  480.   | WS_BORDER | WS_TABSTOP,
  481.   rc.right + 72, rc.top + 26, 210, 24, hRet,
  482.   (HMENU)IDE_ALBUM, hInst, NULL );
  483.   return hRet;
  484. }
  485. void doPaint( HWND hWnd )
  486. {
  487.   PAINTSTRUCT p;
  488.   HDC hDC;
  489.   hDC = BeginPaint( hWnd, &p );
  490.   if ( !hDC )
  491.     return;
  492.   EndPaint( hWnd, &p );
  493. }
  494. void handleToolbarNotify( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  495. {
  496. #if 0
  497.   LPTOOLTIPTEXT lpt = (LPTOOLTIPTEXT)lParam;
  498.   if ( lpt->hdr.code == TTN_NEEDTEXT )
  499.     {
  500.       // we should put in tool-text code here
  501.       //OutputDebugString( "Got a TTN_NEEDTEXT" );
  502.     }
  503. #else
  504.   hWnd = hWnd; uMsg = uMsg; wParam = wParam; lParam = lParam;
  505. #endif
  506. }
  507. int WindowHeight( HWND hWnd )
  508. {
  509.   RECT rc;
  510.   GetWindowRect( hWnd, &rc );
  511.   return ( rc.bottom - rc.top );
  512. }
  513. void DoCDDBQuery( HWND hWnd )
  514. {
  515.   DWORD dwThreadID;
  516.   bInCDDBQuery = TRUE;
  517.   CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DoCDDBQueryThread,
  518. (LPVOID)hWnd, 0, &dwThreadID );
  519. }
  520. DWORD DoCDDBQueryThread( LPVOID lpParam )
  521. {
  522.   CDDBQUERYITEM cdq[5];
  523.   CDDBQUERY query;
  524.   char linebuf[81];
  525.   int i;
  526.   BOOL bCDDB = FALSE;
  527.   char *buf, *p;
  528.   HWND hWnd = (HWND)lpParam;
  529.   ZeroMemory( cdq, sizeof(cdq) );
  530.   buf = (char *)GlobalAlloc( GPTR, 32000 );
  531. #if 1
  532.   CDDBSetOption( CDDB_OPT_USECDPLAYERINI, "", TRUE );
  533. #endif
  534.   CDDBSetOption( CDDB_OPT_SERVER, szCDDBServer, 0 );
  535.   CDDBSetOption( CDDB_OPT_CGI, szCGI, 0 );
  536.   CDDBSetOption( CDDB_OPT_USEPROXY, "", bUseProxy );
  537.   if ( bUseProxy )
  538.     {
  539.       CDDBSetOption( CDDB_OPT_PROXY, szProxyAddr, 0 );
  540.       CDDBSetOption( CDDB_OPT_PROXYPORT, "", iProxyPort );
  541.     }
  542.   CDDBSetOption( CDDB_OPT_USER, "user@akrip.sourceforge.net", 0 );
  543.   CDDBSetOption( CDDB_OPT_AGENT, "xtractor 0.12", 0 );
  544.   SetStatusMessage( "Contacting CDDB Server..." );
  545.   query.num = 5;
  546.   query.q = cdq;
  547.   bCDDB = (CDDBQuery( hCD, &query ) == SS_COMP);
  548. #if 0
  549.   if ( !bCDDB )
  550.     OutputDebugString( "Something's not quite right here..." );
  551.   wsprintf( linebuf, "After CDDBQuery(), num == %d", query.num );
  552.   OutputDebugString( linebuf );
  553. #endif
  554.   if ( bCDDB && (query.num == 0) )
  555.     {
  556.       SetStatusMessage( "No matches in CDDB database..." );
  557.     }
  558.   if ( query.num )
  559.     {
  560.       // If we're in the middle of a rip operation, just use the first one
  561.       // as a default.  Otherwise, pop up a dialog to let the user choose
  562.       // which one to use
  563.       if ( bRippingTracks || (query.num == 1) )
  564. {
  565.   SetStatusMessage( "Retrieving CD info..." );
  566.   query.num = 0;
  567.   bCDDB = (CDDBGetDiskInfo( &cdq[0], buf, 32000 ) == SS_COMP);
  568.   if ( !bCDDB )
  569.     {
  570.       SetStatusMessage( "Error retrieving CDDB info..." );
  571.     }
  572. }
  573.       else
  574. {
  575.   DialogBoxParam( ghInstance, "MultipleCDDBQueryDialog", hWnd,
  576.   (DLGPROC)MultipleCDDBQueryDlgProc, (LPARAM)&query );
  577.   if ( query.num < 0 )
  578.     {
  579.       SetStatusMessage( "CDDB Query cancelled..." );
  580.       bCDDB = FALSE;
  581.     }
  582.   else
  583.     {
  584.       SetStatusMessage( "Retrieving CD info..." );
  585.       bCDDB = (CDDBGetDiskInfo( &cdq[query.num], buf, 32000 ) == SS_COMP);
  586.       if ( !bCDDB )
  587. {
  588.   SetStatusMessage( "Error retrieving CDDB info..." );
  589. }
  590.     }
  591. }
  592.     }
  593.   // probably want to pop up an error message here
  594.   if ( !bCDDB )
  595.     {
  596.       bInCDDBQuery = FALSE;
  597.       GlobalFree( (HGLOBAL)buf );  
  598.       return 0;
  599.     }
  600.   SetEditItemText( IDE_ARTIST, cdq[query.num].artist );
  601.   SetEditItemText( IDE_ALBUM, cdq[query.num].title );
  602.   id3CDDBCat2Genre( cdq[query.num].categ );
  603.   p = buf;
  604.   i = 0;
  605.   while( p && *p )
  606.     {
  607.       GetLineFromBuf( linebuf, &p, 81 );
  608.       if ( !strncmp( linebuf, "TTITLE", 6 ) )
  609. {
  610.   SetTrackText( linebuf, i );
  611.   i++;
  612. }
  613.       else if ( linebuf[0] == '.' )
  614. p = NULL;     // last line read
  615.     }
  616.   GlobalFree( (HGLOBAL)buf );  
  617.   bInCDDBQuery = FALSE;
  618.   UpdateStatusBar();
  619.   return 0;
  620. }
  621. void SetTrackText( char *buf, int i )
  622. {
  623.   char *p;
  624.   p = strstr( buf, "=" );
  625.   if ( p )
  626.     {
  627.       p++;
  628.       if ( *p )
  629. SendMessage( hTrackWnd, WM_SETTRACKTEXT, (WPARAM)i, (LPARAM)p );
  630.     }
  631. }
  632. void RefreshTrackList( void )
  633. {
  634.   ADDTRACK at;
  635.   TOC toc;
  636.   int i;
  637.   SendMessage( hTrackWnd, WM_DELTRACK, ALLTRACKS, 0L );
  638.   ZeroMemory( &toc, sizeof(TOC) );
  639.   ModifyCDParms( hCD, CDP_MSF, (DWORD)FALSE );
  640.   ReadTOC( hCD, &toc );
  641.   for( i = toc.firstTrack; i <= toc.lastTrack; i++ )
  642.     {
  643.       TOCTRACK *t;
  644.       int idx;
  645.       idx = i - toc.firstTrack;
  646.       ZeroMemory( &at, sizeof(at) );
  647.       wsprintf( at.name, "Track %d", i );
  648.       t = &(toc.tracks[idx]);
  649.       MSB2DWORD( &(at.start), t->addr );
  650.       if ( t->ADR & 0x04 )
  651. {
  652.   // will need to fix the leadout detection code here
  653.   at.bData = TRUE;
  654.   lstrcpy( at.name, "Data Track" );
  655. }
  656.       t = &(toc.tracks[idx+1]);
  657.       MSB2DWORD( &(at.len), t->addr );
  658.       at.len -= at.start;
  659.       #define LEADOUT  (150*75)
  660.       // if the next track is a data track, subtract 150 seconds of leadout
  661.       if ( (t->ADR & 0x04) && (at.len > LEADOUT) )
  662. at.len -= LEADOUT;
  663.       SendMessage( hTrackWnd, WM_ADDTRACK, 0, (LPARAM)&at );
  664.     }
  665. }
  666. /*
  667.  * Save parameters to the registry
  668.  */
  669. void DeinitAKRip( void )
  670. {
  671.   HKEY hKey;
  672.   DWORD dwDisposition, driveInfo, dwAutoTOC;
  673.   DWORD dwTmp;
  674.   LONG retVal;
  675.   retVal = RegCreateKeyEx( HKEY_LOCAL_MACHINE, regKeyName, 0L,
  676.  "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  677.  NULL, &hKey, &dwDisposition );
  678.   if ( retVal != ERROR_SUCCESS )
  679.     {
  680.       return;
  681.     }
  682.   RegSetValueEx( hKey, "numRip", 0L, REG_DWORD, (BYTE *)(&maxRip),
  683.  sizeof(DWORD) );
  684.   RegSetValueEx( hKey, "jitterCheck", 0L, REG_DWORD, (LPBYTE)&jitterCheck,
  685.  4L );
  686.   RegSetValueEx( hKey, "overlap", 0L, REG_DWORD, (LPBYTE)&numOverlap, 4L );
  687.   RegSetValueEx( hKey, "readMode", 0L, REG_DWORD, (LPBYTE)&readMode, 4L );
  688.   dwAutoTOC = (DWORD)bAutoTOC;
  689.   RegSetValueEx( hKey, "autoTOC", 0L, REG_DWORD, (LPBYTE)&dwAutoTOC, 4L );
  690.   dwTmp = (DWORD)bAutoCheck;
  691.   RegSetValueEx( hKey, "autoCheck", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  692.   dwTmp = (DWORD)bMP3;
  693.   RegSetValueEx( hKey, "MP3", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  694.   dwTmp = (DWORD)wBitrate;
  695.   RegSetValueEx( hKey, "bitrate", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  696.   dwTmp = (DWORD)wMaxBitrate;
  697.   RegSetValueEx( hKey, "maxbitrate", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  698.   dwTmp = (DWORD)wMode;
  699.   RegSetValueEx( hKey, "mpegmode", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  700.   dwTmp = (DWORD)bID3;
  701.   RegSetValueEx( hKey, "id3level", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  702.   dwTmp = bCRC;
  703.   RegSetValueEx( hKey, "crc", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  704.   dwTmp = bUseProxy;
  705.   RegSetValueEx( hKey, "useproxy", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  706.   dwTmp = iProxyPort;
  707.   RegSetValueEx( hKey, "proxyport", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  708.   RegSetValueEx( hKey, "proxyaddr", 0L, REG_SZ, szProxyAddr, lstrlen(szProxyAddr)+1 );
  709.   RegSetValueEx( hKey, "cddbaddr", 0L, REG_SZ, szCDDBServer, lstrlen(szCDDBServer)+1 );
  710.   RegSetValueEx( hKey, "cddbcgi", 0L, REG_SZ, szCGI, lstrlen(szCGI)+1 );
  711.   dwTmp = bCDDB;
  712.   RegSetValueEx( hKey, "enablecddb", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  713.   dwTmp = iEncoder;
  714.   RegSetValueEx( hKey, "encoder", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  715.   dwTmp = (DWORD)bHiColor;
  716.   RegSetValueEx( hKey, "hicolor", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  717.   dwTmp = 0;
  718.   if ( bVBR )
  719.     dwTmp |= 0x80000000;
  720.   if ( bVBRHeader )
  721.     dwTmp |= 0x40000000;
  722.   dwTmp |= ( (wMaxBitrate & 0x1FF) << 21 );
  723.   dwTmp |= ( (nQuality & 0x03) << 19 );
  724.   dwTmp |= ( (nVBRQuality & 0x0F) << 15 );
  725.   RegSetValueEx( hKey, "lameopts", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  726.   if ( cdlistIdx >= 0 )
  727.     {
  728.       driveInfo = ((DWORD)bReadType) << 24 |
  729. ((DWORD)cdlist.cd[cdlistIdx].ha) << 16 |
  730. ((DWORD)cdlist.cd[cdlistIdx].tgt) << 8 |
  731. ((DWORD)cdlist.cd[cdlistIdx].lun);
  732.       RegSetValueEx( hKey, "driveInfo", 0L, REG_DWORD,
  733.      (LPBYTE)&driveInfo, 4L );
  734.     }
  735.   else
  736.     RegDeleteValue( hKey, "driveInfo" );
  737.   RegSetValueEx( hKey, "wavOutputdir", 0L, REG_SZ, (LPBYTE)szWavOutputDir,
  738.  lstrlen( szWavOutputDir)+1 );
  739.   RegSetValueEx( hKey, "mp3Outputdir", 0L, REG_SZ, (LPBYTE)szMP3OutputDir,
  740.  lstrlen( szMP3OutputDir)+1 );
  741.   RegCloseKey( hKey );
  742. }
  743. /*
  744.  * void InitAKRip( void );
  745.  *
  746.  * Reads initialization values from the registry, if present.  Currently
  747.  * looks for the following values:
  748.  *   numRip      - (DWORD) number of frames to read at once
  749.  *   jitterCheck - (DWORD) number of frames to try to match
  750.  *   overlap     - (DWORD) number of frames of overlap (at least
  751.  *                 jitterCheck + 1
  752.  *   autoTOC     - (DWORD) boolean, whether to automatically scan the TOC on
  753.  *                 startup
  754.  *   driveInfo   - (DWORD) ha, tgt, lun identifier of last CD unit used
  755.  *   driveString - (REG_SZ) string identifier of CD unit
  756.  *   driveVendor - (REG_SZ) vendor identifier of CD unit
  757.  *   driveProdID - (REG_SZ) product identifier of CD unit
  758.  *   driveRev    - (REG_SZ) hardware revision number of CD unit
  759.  *   driveVendSp - (REG_SZ) vendor specific info for CD unit
  760.  *   
  761.  */
  762. void InitAKRip( void )
  763. {
  764.   HKEY hKey;
  765.   DWORD dwDisposition, driveInfo, dwAutoTOC;
  766.   DWORD dwTmp;
  767.   LONG retVal;
  768.   CDREC cd;
  769.   // scan the list of available cd drives
  770.   ZeroMemory( &cdlist, sizeof(CDLIST) );
  771.   cdlist.max = MAXCDLIST;
  772.   GetCDList( &cdlist );
  773.   cdlistIdx = -1;
  774.   memset( &cd, 0, sizeof(cd) );
  775.   memset( validFnameChar, 0xFF, 256 );
  776.   validFnameChar['\'] = 0;
  777.   validFnameChar['/'] = 0;
  778.   validFnameChar[':'] = 0;
  779.   validFnameChar['*'] = 0;
  780.   validFnameChar['?'] = 0;
  781.   validFnameChar['"'] = 0;
  782.   validFnameChar['<'] = 0;
  783.   validFnameChar['>'] = 0;
  784.   validFnameChar['|'] = 0;
  785.   retVal = RegCreateKeyEx( HKEY_LOCAL_MACHINE, regKeyName, 0L,
  786.  "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  787.  NULL, &hKey, &dwDisposition );
  788.   if ( retVal != ERROR_SUCCESS )
  789.     {
  790.       // UserOutput( UO_ERROPENREG, regKeyName, retVal );
  791.       return;
  792.     }
  793.   if ( !readRegDWORD( hKey, "numRip", &maxRip ) )
  794.     {
  795.       maxRip = 26;  /* default value */
  796.       RegSetValueEx( hKey, "numRip", 0L, REG_DWORD, (BYTE *)(&maxRip),
  797.      sizeof(DWORD) );
  798.     }
  799.   if ( !readRegDWORD( hKey, "jitterCheck", &jitterCheck ) )
  800.     {
  801.       jitterCheck = 1;
  802.       RegSetValueEx( hKey, "jitterCheck", 0L, REG_DWORD,
  803.      (LPBYTE)&jitterCheck, 4L );
  804.     }
  805.   if ( !readRegDWORD( hKey, "overlap", &numOverlap ) )
  806.     {
  807.       numOverlap = jitterCheck + 2;
  808.       RegSetValueEx( hKey, "overlap", 0L, REG_DWORD,
  809.      (LPBYTE)&numOverlap, 4L );
  810.     }
  811.   if ( !readRegDWORD( hKey, "autoTOC", &dwAutoTOC ) )
  812.     {
  813.       dwAutoTOC = 1;
  814.       RegSetValueEx( hKey, "autoTOC", 0L, REG_DWORD,
  815.      (LPBYTE)&dwAutoTOC, 4L );
  816.     }
  817.   bAutoTOC = (BOOL)dwAutoTOC;
  818.   if ( !readRegDWORD( hKey, "autoCheck", &dwAutoTOC ) )
  819.     {
  820.       dwAutoTOC = 1;
  821.       RegSetValueEx( hKey, "autoCheck", 0L, REG_DWORD,
  822.      (LPBYTE)&dwAutoTOC, 4L );
  823.     }
  824.   bAutoCheck = (BOOL)dwAutoTOC;
  825.   if ( !readRegDWORD( hKey, "readMode", &readMode ) )
  826.     {
  827.       readMode = CDRM_JITTERONERR;
  828.       RegSetValueEx( hKey, "readMode", 0L, REG_DWORD,
  829.      (LPBYTE)&readMode, 4L );
  830.     }
  831.   if ( readRegDWORD( hKey, "MP3", &dwTmp ) )
  832.     bMP3 = (BOOL)dwTmp;
  833.   else
  834.     {
  835.       bMP3 = FALSE;
  836.       dwTmp = 0L;
  837.       RegSetValueEx( hKey, "MP3", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  838.     }
  839.   if ( readRegDWORD( hKey, "bitrate", &dwTmp ) )
  840.     wBitrate = (WORD)dwTmp;
  841.   else
  842.     {
  843.       wBitrate = 192;
  844.       dwTmp = 192L;
  845.       RegSetValueEx( hKey, "bitrate", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  846.     }
  847.   if ( readRegDWORD( hKey, "maxbitrate", &dwTmp ) )
  848.     wMaxBitrate = (WORD)dwTmp;
  849.   else
  850.     {
  851.       wMaxBitrate = 320;
  852.       dwTmp = 320L;
  853.       RegSetValueEx( hKey, "maxbitrate", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  854.     }
  855.   if ( readRegDWORD( hKey, "mpegmode", &dwTmp ) )
  856.     wMode = (WORD)dwTmp;
  857.   else
  858.     {
  859.       wMode = BE_MP3_MODE_STEREO;
  860.       dwTmp = BE_MP3_MODE_STEREO;
  861.       RegSetValueEx( hKey, "mpegmode", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  862.     }
  863.   if ( readRegDWORD( hKey, "id3level", &dwTmp ) )
  864.     bID3 = (BOOL)dwTmp;
  865.   else
  866.     {
  867.       bID3 = FALSE;
  868.       dwTmp = (DWORD)FALSE;
  869.       RegSetValueEx( hKey, "id3level", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  870.     }
  871.   if ( readRegDWORD( hKey, "crc", &dwTmp ) )
  872.     bCRC = (BOOL)dwTmp;
  873.   else
  874.     {
  875.       bCRC = FALSE;
  876.       dwTmp = (DWORD)FALSE;
  877.       RegSetValueEx( hKey, "crc", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  878.     }
  879.   if ( readRegDWORD( hKey, "useproxy", &dwTmp ) )
  880.     bUseProxy = (BOOL)dwTmp;
  881.   else
  882.     {
  883.       bUseProxy = FALSE;
  884.       dwTmp = (DWORD)FALSE;
  885.       RegSetValueEx( hKey, "useproxy", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  886.     }
  887.   if ( readRegDWORD( hKey, "lameopts", &dwTmp ) )
  888.     {
  889.       bVBR        = (BOOL)(dwTmp & 0x80000000);
  890.       bVBRHeader  = (BOOL)(dwTmp & 0x40000000);
  891.       wMaxBitrate = (dwTmp >> 21) & 0x1FF;
  892.       nQuality    = (dwTmp >> 19) & 0x03;
  893.       nVBRQuality = (dwTmp >> 15) & 0x0F;
  894.     }
  895.   if ( readRegDWORD( hKey, "encoder", &dwTmp ) )
  896.     iEncoder = (int)dwTmp;
  897.   else
  898.     {
  899.       iEncoder = NOENCODER;
  900.       dwTmp = NOENCODER;
  901.       RegSetValueEx( hKey, "encoder", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  902.    }
  903.   if ( readRegDWORD( hKey, "proxyport", &dwTmp ) )
  904.     iProxyPort = (int)dwTmp;
  905.   else
  906.     {
  907.       iProxyPort = 0;
  908.       dwTmp = 0;
  909.       RegSetValueEx( hKey, "proxyport", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  910.     }
  911.   if ( !readRegSZ( hKey, "proxyaddr", szProxyAddr, 81 ) )
  912.     lstrcpy( szProxyAddr, "" );
  913.   if ( !readRegSZ( hKey, "cddbaddr", szCDDBServer, 81 ) )
  914.     lstrcpy( szCDDBServer, "www.freedb.org" );
  915.   if ( !readRegSZ( hKey, "cddbcgi", szCGI, 81 ) )
  916.     lstrcpy( szCGI, "/~cddb/cddb.cgi" );
  917.   if ( readRegDWORD( hKey, "enablecddb", &dwTmp ) )
  918.     bCDDB = (BOOL)dwTmp;
  919.   else
  920.     {
  921.       bCDDB = FALSE;
  922.       dwTmp = 0;
  923.       RegSetValueEx( hKey, "enablecddb", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  924.     }
  925.   if ( readRegDWORD( hKey, "hicolor", &dwTmp ) )
  926.     bHiColor = (BOOL)dwTmp;
  927.   else
  928.     {
  929.       bHiColor = DisplayIsHiColor();
  930.       dwTmp = (DWORD)bHiColor;
  931.       RegSetValueEx( hKey, "hicolor", 0L, REG_DWORD, (LPBYTE)&dwTmp, 4L );
  932.     }
  933.   if ( readRegDWORD( hKey, "driveInfo", &driveInfo ) )
  934.     {
  935.       //      BYTE bRead;
  936.       GETCDHAND cdh;
  937.       cd.ha = (BYTE)((0x00FF0000 & driveInfo) >> 16);
  938.       cd.tgt = (BYTE)((0x0000FF00 & driveInfo) >> 8 );
  939.       cd.lun = (BYTE)(0x000000FF & driveInfo);
  940.       bReadType = (BYTE)((0xFF000000 & driveInfo) >> 24);
  941.       memset( &cdh, 0, sizeof(GETCDHAND) );
  942.       cdh.size       = sizeof(GETCDHAND);
  943.       cdh.ver        = 1;
  944.       cdh.ha         = cd.ha;
  945.       cdh.tgt        = cd.tgt;
  946.       cdh.lun        = cd.lun;
  947.       cdh.readType   = bReadType;
  948.       cdh.numOverlap = numOverlap;
  949.       cdh.numJitter  = jitterCheck;
  950.       hCD = GetCDHandle( &cdh );
  951.       if ( !hCD )
  952. MessageBox( NULL, "Unable to allocate default CD device", "X-Tractor",
  953.     MB_APPLMODAL | MB_ICONSTOP | MB_OK );
  954.       else
  955. {
  956.   BYTE i;
  957.   // locate the drive in the list of available drives
  958.   for( i = 0; i < cdlist.num; i++ )
  959.     {
  960.       if ( (cdh.ha  == cdlist.cd[i].ha) &&
  961.    (cdh.tgt == cdlist.cd[i].tgt) &&
  962.    (cdh.lun == cdlist.cd[i].lun) )
  963. cdlistIdx = i;
  964.     }
  965. }
  966.     }
  967.   else
  968.     {
  969.       hCD = findAvailableCD( );
  970.     }
  971.   if ( !readRegSZ( hKey, "wavOutputDir", szWavOutputDir, MAX_PATH + 1 ) )
  972.     GetCurrentDirectory( MAX_PATH + 1, szWavOutputDir );
  973.   if ( !readRegSZ( hKey, "mp3OutputDir", szMP3OutputDir, MAX_PATH + 1 ) )
  974.     GetCurrentDirectory( MAX_PATH + 1, szMP3OutputDir );
  975.   asSetID3Info( ID3_TITLE, "", 0 );
  976.   asSetID3Info( ID3_ARTIST, "", 0 );
  977.   asSetID3Info( ID3_ALBUM, "", 0 );
  978.   asSetID3Info( ID3_YEAR, "", 0 );
  979.   asSetID3Info( ID3_GENRE, NULL, 0 );
  980.   if ( hKey )
  981.     RegCloseKey( hKey );
  982. }
  983. HCDROM findAvailableCD( void )
  984. {
  985.   GETCDHAND cdh;
  986.   BYTE i;
  987.   if ( hCD )
  988.     {
  989.       CloseCDHandle( hCD );
  990.       hCD = NULL;
  991.     }
  992.   ZeroMemory( &cdh, sizeof(cdh) );
  993.   for( i = 0; i < cdlist.num && !hCD; i++ )
  994.     {
  995.       cdh.size        = sizeof(GETCDHAND);
  996.       cdh.ver         = 1;
  997.       cdh.ha          = cdlist.cd[i].ha;
  998.       cdh.tgt         = cdlist.cd[i].tgt;
  999.       cdh.lun         = cdlist.cd[i].lun;
  1000.       cdh.readType    = bReadType;
  1001.       cdh.numOverlap  = numOverlap;
  1002.       cdh.numJitter   = jitterCheck;
  1003.       hCD = GetCDHandle( &cdh );
  1004.       if ( hCD )
  1005. cdlistIdx = i;
  1006.     }
  1007.   return hCD;
  1008. }
  1009. /*
  1010.  * Reads a DWORD from the registry given an already open key
  1011.  * The value read is stored into pdw, and the function returns
  1012.  * 0 if it fails
  1013.  */
  1014. int readRegDWORD( HKEY hKey, LPCTSTR lpszValue, DWORD *pdw )
  1015. {
  1016.   DWORD dwSize = 4L;
  1017.   DWORD dwType;
  1018.   LONG retVal;
  1019.   retVal = RegQueryValueEx( hKey, lpszValue, NULL, &dwType, (LPBYTE)pdw,
  1020.     &dwSize );
  1021.   if ( retVal != ERROR_SUCCESS )
  1022.     {
  1023.       return 0;
  1024.     }
  1025.   return -1;
  1026. }
  1027.  
  1028. /*
  1029.  * Reads an ASCIIZ string from the registry given an already open key
  1030.  * The value read is stored into lpszData, and the function returns
  1031.  * 0 if it fails
  1032.  */
  1033. int readRegSZ( HKEY hKey, LPCTSTR lpszValue, LPSTR lpszData, DWORD dwDataLen )
  1034. {
  1035.   DWORD dwType;
  1036.   LONG retVal;
  1037.   retVal = RegQueryValueEx( hKey, lpszValue, NULL, &dwType, (LPBYTE)lpszData,
  1038.     &dwDataLen );
  1039.   if ( (retVal != ERROR_SUCCESS) || (dwType != REG_SZ) )
  1040.     {
  1041.       return 0;
  1042.     }
  1043.   return -1;
  1044. }
  1045. /*
  1046.  * Sets the registry to disable autoplay under Win95.  Probably won't
  1047.  * work under NT due to security settings
  1048.  */
  1049. void disableAutoPlay( void )
  1050. {
  1051.   HKEY hKey;
  1052.   unsigned long ulDisable = (unsigned long)0xFF;
  1053.   DWORD dwDataSize = sizeof( ulDisable );
  1054.   DWORD dwDataType;
  1055.   LONG lErr = 0;
  1056.   if ( ( lErr = RegOpenKeyEx( HKEY_CURRENT_USER, regAutoPlay, 0,
  1057.      KEY_ALL_ACCESS, &hKey ) ) == ERROR_SUCCESS )
  1058.     {
  1059.       if ( RegQueryValueEx( hKey, "NoDriveTypeAutoRun", 0, NULL,
  1060.     (unsigned char *)&ulOldAutorun,
  1061.     &dwDataSize ) == ERROR_SUCCESS )
  1062. {
  1063.   RegSetValueEx( hKey, "NoDriveTypeAutoRun", 0, REG_BINARY,
  1064.  (unsigned char *)&ulDisable, 4 );
  1065. }
  1066.       else
  1067. ulOldAutorun = (unsigned long)0x95;
  1068.       RegFlushKey( hKey );
  1069.       RegCloseKey( hKey );
  1070.     }
  1071.   if ( ( lErr = RegOpenKeyEx( HKEY_CLASSES_ROOT, regAutoAudioCD, 0,
  1072.                               KEY_ALL_ACCESS, &hKey ) ) == ERROR_SUCCESS )
  1073.     {
  1074.       dwDataSize = 256;
  1075.       if ( RegQueryValueEx( hKey, "", NULL, &dwDataType,
  1076.                             szOldAutoPlay,
  1077.                             &dwDataSize ) == ERROR_SUCCESS )
  1078.         {
  1079.           RegSetValueEx( hKey, "", 0, REG_SZ, (unsigned char *)"", 1 );
  1080.         }
  1081.       RegFlushKey( hKey );
  1082.       RegCloseKey( hKey );
  1083.     }
  1084. }
  1085. void restoreAutoPlay( void )
  1086. {
  1087.   HKEY hKey;
  1088.   if ( RegOpenKeyEx( HKEY_CURRENT_USER, regAutoPlay, 0,
  1089.      KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS )
  1090.     {
  1091.       RegSetValueEx( hKey, "NoDriveTypeAutoRun", 0, REG_BINARY,
  1092.      (unsigned char *)&ulOldAutorun, 4 );
  1093.       RegFlushKey( hKey );
  1094.       RegCloseKey( hKey );
  1095.     }
  1096.   if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, regAutoAudioCD, 0,
  1097.                      KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS )
  1098.     {
  1099.       RegSetValueEx( hKey, "", 0, REG_SZ,
  1100.                      (unsigned char *)&szOldAutoPlay,
  1101.                      lstrlen(szOldAutoPlay)+1 );
  1102.       RegFlushKey( hKey );
  1103.       RegCloseKey( hKey );
  1104.     }
  1105. }
  1106. BOOL DirExists( char *dir )
  1107. {
  1108.   char curDir[MAX_PATH+1];
  1109.   //  BOOL bSet;
  1110.   if ( !GetCurrentDirectory( MAX_PATH + 1, curDir ) )
  1111.     return FALSE;
  1112.   if ( !SetCurrentDirectory( dir ) )
  1113.      return FALSE;
  1114.   SetCurrentDirectory( curDir );
  1115.   return TRUE;
  1116. }
  1117. void MSB2DWORD( DWORD *d, BYTE *b )
  1118. {
  1119.   DWORD retVal;
  1120.   retVal = (DWORD)b[0];
  1121.   retVal = (retVal<<8) + (DWORD)b[1];
  1122.   retVal = (retVal<<8) + (DWORD)b[2];
  1123.   retVal = (retVal<<8) + (DWORD)b[3];
  1124.   *d = retVal;
  1125. }
  1126. void GetEditItemText( int iCtlId, HWND hCtl )
  1127. {
  1128.   char buf[31];
  1129.   ZeroMemory( buf, 31 );
  1130.   SendMessage( hCtl, WM_GETTEXT, 31, (LPARAM)buf );
  1131.   switch( iCtlId )
  1132.     {
  1133.     case IDE_ARTIST:
  1134.       asSetID3Info( ID3_ARTIST, buf, 0 );
  1135.       break;
  1136.     case IDE_ALBUM:
  1137.       asSetID3Info( ID3_ALBUM, buf, 0 );
  1138.       break;
  1139.     }
  1140. }
  1141. void SetEditItemText( int iCtlId, char *s )
  1142. {
  1143.   switch( iCtlId )
  1144.     {
  1145.     case IDE_ARTIST:
  1146.       SendMessage( hEditArtist, WM_SETTEXT, 0, (LPARAM)s );
  1147.       break;
  1148.     case IDE_ALBUM:
  1149.       SendMessage( hEditAlbum, WM_SETTEXT, 0, (LPARAM)s );
  1150.       break;
  1151.     }
  1152. }
  1153. void CheckEnableID3MenuItem( HWND hWnd )
  1154. {
  1155.   HMENU hPopup;
  1156.   hPopup = GetSubMenu( GetMenu(hWnd), 3 ); // get handle to Tools menu
  1157.   if ( bID3 )
  1158.     CheckMenuItem( hPopup, IDM_ENABLEID3, MF_BYCOMMAND | MF_CHECKED );
  1159.   else
  1160.     CheckMenuItem( hPopup, IDM_ENABLEID3, MF_BYCOMMAND | MF_UNCHECKED );
  1161. }
  1162. void CheckEnableCDDBMenuItem( HWND hWnd )
  1163. {
  1164.   HMENU hPopup;
  1165.   hPopup = GetSubMenu( GetMenu(hWnd), 3 ); // get handle to Tools menu
  1166.   if ( bCDDB )
  1167.     CheckMenuItem( hPopup, IDM_ENABLECDDB, MF_BYCOMMAND | MF_CHECKED );
  1168.   else
  1169.     CheckMenuItem( hPopup, IDM_ENABLECDDB, MF_BYCOMMAND | MF_UNCHECKED );
  1170. }
  1171. void CheckEnableHiColorMenuItem( HWND hWnd )
  1172. {
  1173.   HMENU hPopup;
  1174.   hPopup = GetSubMenu( GetMenu(hWnd), 2 );  //options menu
  1175.   if ( bHiColor )
  1176.     CheckMenuItem( hPopup, IDM_HICOLOR, MF_BYCOMMAND | MF_CHECKED );
  1177.   else
  1178.     CheckMenuItem( hPopup, IDM_HICOLOR, MF_BYCOMMAND | MF_UNCHECKED );
  1179. }
  1180. void ShowHelpFile( HWND hWnd, int topic )
  1181. {
  1182.   char buf[MAX_PATH+1];
  1183.   topic = topic;
  1184.   GetCurrentDirectory( MAX_PATH+1, buf );
  1185.   lstrcat( buf, "\help" );
  1186.   ShellExecute( hWnd, "open", "index.html", NULL, buf, SW_SHOWNORMAL );
  1187. }
  1188. void setRipTrackStatus( LPENCODETHREAD e )
  1189. {
  1190.   char buf[61];
  1191.   char buf2[81];
  1192.   char *p = buf;
  1193.   double d;
  1194.   int a,b;
  1195.   time( &e->tnow );
  1196.   d = difftime( e->tnow, e->tstart );
  1197.   switch( e->status )
  1198.     {
  1199.     case EST_SUCCESS:
  1200.       lstrcpy( buf, "OK, " );
  1201.       DiffTimeToString( d, buf+4 );
  1202.       p += lstrlen( buf );
  1203.       d = ((double)(e->trackLen/75)) / d;
  1204.       a = d;
  1205.       b = ((d-(double)a) * 100.0);
  1206.       wsprintf( p, ", %s: %d.%02dx", bMP3?"rip/encode":"rip", a, b );
  1207.       wsprintf( buf2, "lstrlen(buf) == %d", lstrlen(buf) );
  1208.       OutputDebugString( buf2 );
  1209.       break;
  1210.     case EST_ERROR:
  1211.       wsprintf( buf, "Error: 0x%04X", GetAspiLibAspiError() );
  1212.       break;
  1213.     case EST_ABORTED:
  1214.       lstrcpy( buf, "Rip Aborted" );
  1215.       break;
  1216.     default:
  1217.       lstrcpy( buf, "" );
  1218.       break;
  1219.     }
  1220.   SendMessage( hTrackWnd, WM_SETTRACKSTATUS, (WPARAM)e->idx,
  1221.        (LPARAM)buf );
  1222. }
  1223. void DiffTimeToString( double d, char *buf )
  1224. {
  1225.   unsigned long hrs, min, sec;
  1226.   
  1227.   hrs = (unsigned long)(d / 3600.0);
  1228.   min = (unsigned long)((d - (double)((hrs) * 3600))/60.0);
  1229.   sec = ((unsigned long)d) - (hrs)*3600 - (min)*60;
  1230.   wsprintf( buf, "%02d:%02d", hrs * 60 + min, sec );
  1231. }
  1232. static void GetLineFromBuf( char *tgt, char **src, int len )
  1233. {
  1234.   char *p;
  1235.   if ( !src || !*src || !tgt )
  1236.     return;
  1237.   p = *src;
  1238.   ZeroMemory( tgt, len );
  1239.   len--;
  1240.   while( *p && len )
  1241.     {
  1242.       if ( *p == 'n' )
  1243.         break;
  1244.       *tgt++ = *p;
  1245.       p++;
  1246.       len--;
  1247.     }
  1248.   // advance *src to end of last read string
  1249.   if ( *p == 'n' )
  1250.     p++;
  1251.   *src = p;
  1252.   len = lstrlen( tgt );
  1253.   if ( tgt[len-2] == 'r' )
  1254.     tgt[len-2] = '';
  1255.   if ( (tgt[len-1] == 'r') || (tgt[len-1] == 'n') )
  1256.     tgt[len-1] = '';
  1257. }
  1258. #if 0
  1259. LRESULT CALLBACK Edit0Proc( HWND hWnd, UINT uMsg, WPARAM wParam,
  1260.     LPARAM lParam )
  1261. {
  1262.   WNDPROC lpfnWndProc;
  1263.   lpfnWndProc = (WNDPROC)GetWindowLong( hWnd, GWL_USERDATA );
  1264.   logMessage( 0, uMsg, wParam, lParam );
  1265.   return lpfnWndProc( hWnd, uMsg, wParam, lParam );
  1266. }
  1267. LRESULT CALLBACK Edit1Proc( HWND hWnd, UINT uMsg, WPARAM wParam,
  1268.     LPARAM lParam )
  1269. {
  1270.   WNDPROC lpfnWndProc;
  1271.   lpfnWndProc = (WNDPROC)GetWindowLong( hWnd, GWL_USERDATA );
  1272.   logMessage( 1, uMsg, wParam, lParam );
  1273.   return lpfnWndProc( hWnd, uMsg, wParam, lParam );
  1274. }
  1275. LRESULT CALLBACK Edit2Proc( HWND hWnd, UINT uMsg, WPARAM wParam,
  1276.     LPARAM lParam )
  1277. {
  1278.   WNDPROC lpfnWndProc;
  1279.   lpfnWndProc = (WNDPROC)GetWindowLong( hWnd, GWL_USERDATA );
  1280.   logMessage( 2, uMsg, wParam, lParam );
  1281.   return lpfnWndProc( hWnd, uMsg, wParam, lParam );
  1282. }
  1283. void logMessage( int which, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1284. {
  1285.   char buf[128];
  1286.   char *p;
  1287.   p = buf;
  1288.   wsprintf( buf, "%d: ", which );
  1289.   p += lstrlen( p );
  1290.   switch( uMsg )
  1291.     {
  1292.     case WM_SETCURSOR:
  1293.     case WM_MOUSEMOVE:
  1294.     case WM_NCHITTEST:
  1295.     case WM_NCMOUSEMOVE:
  1296.     case WM_PAINT:
  1297.     case WM_NCPAINT:
  1298.       return;
  1299.     case WM_MOUSEACTIVATE:
  1300.       wsprintf( p, "WM_MOUSEACTIVATE  0x%08X  0x%08X", wParam, lParam );
  1301.       break;
  1302.     case WM_GETDLGCODE:
  1303.       wsprintf( p, "WM_GETDLGCODE  0x%08X  0x%08X", wParam, lParam );
  1304.       break;
  1305.     case WM_LBUTTONDOWN:
  1306.       wsprintf( p, "WM_LBUTTONDOWN  0x%08X  0x%08X", wParam, lParam );
  1307.       break;
  1308.     case WM_LBUTTONUP:
  1309.       wsprintf( p, "WM_LBUTTONUP  0x%08X  0x%08X", wParam, lParam );
  1310.       break;
  1311.     case WM_KILLFOCUS:
  1312.       wsprintf( p, "WM_KILLFOCUS  0x%08X  0x%08X", wParam, lParam );
  1313.       break;
  1314.     case WM_SETFOCUS:
  1315.       wsprintf( p, "WM_SETFOCUS  0x%08X  0x%08X", wParam, lParam );
  1316.       break;
  1317.     case WM_CAPTURECHANGED:
  1318.       wsprintf( p, "WM_CAPTURECHANGED  0x%08X  0x%08X", wParam, lParam );
  1319.       break;
  1320.     default:
  1321.       wsprintf( p, "unknown 0x%04X (%d)", uMsg, uMsg );
  1322.       break;
  1323.     }
  1324.   OutputDebugString( buf );
  1325. }
  1326. #endif
  1327. void dbprintf( char *fmt, ... )
  1328. {
  1329.   char buf[512];
  1330.   va_list arg;
  1331.   va_start( arg, fmt );
  1332.   vsprintf( buf, fmt, arg );
  1333.   OutputDebugString( buf );
  1334.   va_end( arg );
  1335. }
  1336. /*
  1337.  * Attempt to determine the version of comctl32.dll available.
  1338.  */
  1339. #if (!_CONFIG_DLLVERINFO)
  1340. typedef struct
  1341. {
  1342.   DWORD cbSize;
  1343.   DWORD dwMajorVersion;
  1344.   DWORD dwMinorVersion;
  1345.   DWORD dwBuildNumber;
  1346.   DWORD dwPlatformID;
  1347. } DLLVERSIONINFO;
  1348. typedef HRESULT CALLBACK (*DLLGETVERSIONPROC)(DLLVERSIONINFO *);
  1349. #endif
  1350. DWORD GetDllVersion( LPCTSTR lpszDllName )
  1351. {
  1352.   HINSTANCE hDll;
  1353.   DWORD retVal = 0;
  1354.   hDll = LoadLibrary( lpszDllName );
  1355.   if ( hDll )
  1356.     {
  1357.       DLLGETVERSIONPROC pDllGetVer;
  1358.       pDllGetVer = (DLLGETVERSIONPROC)GetProcAddress( hDll, "DllGetVersion" );
  1359.       if ( pDllGetVer )
  1360. {
  1361.   DLLVERSIONINFO dvi;
  1362.   HRESULT hr;
  1363.   ZeroMemory( &dvi, sizeof(dvi) );
  1364.   dvi.cbSize = sizeof(dvi);
  1365.   hr = (*pDllGetVer)(&dvi);
  1366.   if ( SUCCEEDED(hr) )
  1367.     {
  1368.       retVal = MAKELONG( dvi.dwMajorVersion, dvi.dwMinorVersion );
  1369.     }
  1370.   FreeLibrary( hDll );
  1371. }
  1372.     }
  1373.   return retVal;
  1374. }
  1375. /*
  1376.  * Returns TRUE if color depth >= 16 bpp
  1377.  */
  1378. BOOL DisplayIsHiColor( void )
  1379. {
  1380.   HDC hDC;
  1381.   int iBPP;
  1382.   hDC = GetDC( NULL );
  1383.   iBPP = GetDeviceCaps( hDC, BITSPIXEL );
  1384.   ReleaseDC( NULL, hDC );
  1385.   return (iBPP >= 16);
  1386. }