 /***********************************************************************/
 /* Simple CD Player --- 24 October 1992                                */
 /*                                                                     */
 /* Written by John A. Junod using code ideas presented in the SDK      */
 /* documentation and uses the basic code form from Quick Case.         */
 /*                                                                     */
 /* This program opens "CDAUDIO" when the program starts, keeps it open */
 /* while the program is running and closes it on exit.  This does make */
 /* some actions take less time.  Error recovery is basically non-      */
 /* existant beyond giving the user a basically useless error message.  */
 /*                                                                     */
 /* This program has no "main" window and relies on a dialog box to do  */
 /* everything.                                                         */
 /*                                                                     */
 /* Modify this as much as you wish and redistribute however you wish,  */
 /* but I do ask that you give me some of the credit and that you let   */
 /* other people use the final product for FREE and don't charge some   */
 /* silly shareware fee of $25.                                         */
 /***********************************************************************/

#include "CD.h"

HWND hInst;
HWND hMainWnd;

char szBuffer[4096];  /* general purpose large buffer */
char szBuf[256];      /* general purpose small buffer */
char szTitle[100];    /* window title */

UINT wDeviceID;       /* open cd device id */
int iCDstatus;        /* cd status */

#define CD_STOPPED 0
#define CD_PLAYING 1
#define CD_PAUSED  2
#define CD_NOTRDY  3
#define CD_OPEN    4
char *szStatus[5]={"stopped","playing","paused","notready","open"};

HCURSOR hHourGlass;
HCURSOR hSaveCursor;
HICON hIcon;
BOOL bCanEject;

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
                   LPSTR lpszCmdLine, int nCmdShow)
{
 /***********************************************************************/
 /* HANDLE hInstance;       handle for this instance                    */
 /* HANDLE hPrevInstance;   handle for possible previous instances      */
 /* LPSTR  lpszCmdLine;     long pointer to exec command line           */
 /* int    nCmdShow;        Show code for main window display           */
 /***********************************************************************/

	MCI_OPEN_PARMS mciOpenParms;
	FARPROC	lpMainDlg;
	DWORD		dwMCIerr;

	hInst = hInstance;
	if(hPrevInstance) return(0);
	hHourGlass=LoadCursor(NULL,IDC_WAIT);
	hIcon=LoadIcon(hInst,"CDICON");

	// open the compact disc device
	mciOpenParms.lpstrDeviceType="cdaudio";
	if(dwMCIerr=mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE,
			(DWORD)(LPVOID)&mciOpenParms)) {
		// failed to open, show the error and end this program.
		showMCIError(dwMCIerr);
		return(FALSE);
	}
	// opened successfully
	wDeviceID=mciOpenParms.wDeviceID;

	if(dwMCIerr=CD_GetDeviceInfo(wDeviceID))
		showMCIError(dwMCIerr);

	iCDstatus=CD_GetCurrentStatus(wDeviceID);

	if((lpMainDlg=MakeProcInstance((FARPROC)MainDlg,hInst))==NULL)
 		MessageBox(NULL,"MakeProc Failed","CD Error",MB_OK);
	else
		if(DialogBox(hInst,"CDBox",hMainWnd,lpMainDlg)== -1)
			MessageBox(NULL,"Couldn't create dialog box","CD Error",MB_OK);
		else
			FreeProcInstance(lpMainDlg);

	// close the CD device and exit program
	if(dwMCIerr=mciSendCommand(wDeviceID,MCI_CLOSE,0,NULL))
		showMCIError(dwMCIerr);
	return TRUE;
} /*  End of WinMain                                                    */


BOOL FAR PASCAL MainDlg(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
{
	DWORD dwMCIerr;
	UINT uAUXerr;
	DWORD volume;
	HMENU hMenu;

	switch(message) {
		case WM_INITDIALOG:
			// change the system menus of this dialog box!
			hMenu=GetSystemMenu(hDlg,FALSE);
			RemoveMenu(hMenu,4,MF_BYPOSITION);
			AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
			AppendMenu(hMenu,MF_STRING,IDM_SHAUTH,"About...");
			AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
			AppendMenu(hMenu,MF_STRING,IDM_EJECT,"Eject");
			AppendMenu(hMenu,MF_STRING,IDM_STOP,"Stop");
			AppendMenu(hMenu,MF_STRING,IDM_PAUSE,"Pause");
			AppendMenu(hMenu,MF_STRING,IDM_PLAY,"Play");
			AppendMenu(hMenu,MF_STRING,IDM_BACK,"Backward");
			AppendMenu(hMenu,MF_STRING,IDM_FORWARD,"Forward");
			AppendMenu(hMenu,MF_STRING,IDM_STATUS,"Tracks...");
			// sub-routines use the global hMainWnd as the window to notify
			hMainWnd=hDlg;
			// format the window title line
			wsprintf(szTitle,"CD (%s) %d",
				(LPSTR)szStatus[CD_GetCurrentStatus(wDeviceID)],
				CD_GetCurrentTrack(wDeviceID));
			// display new title
			SetWindowText(hDlg,szTitle);
			// set a timer ~5 seconds to update title
			SetTimer(hDlg,1,5000,NULL);
			return(TRUE);

		// timer click updates title to reflect status of CD
		case WM_TIMER:
		case MM_MCINOTIFY:
			iCDstatus=CD_GetCurrentStatus(wDeviceID);
			// format the window title line
			wsprintf(szBuffer,"CD (%s) %d",
				(LPSTR)szStatus[iCDstatus],
				CD_GetCurrentTrack(wDeviceID));
			// only update it if it changes as we don't like flashing
			if(lstrcmp(szBuffer,szTitle)!=0) {
				lstrcpy(szTitle,szBuffer);
				SetWindowText(hDlg,szTitle);
			}
			break;

		case WM_SYSCOMMAND:
		case WM_COMMAND:
		  switch(wParam) {
		  	// show some useful info???
			case IDM_STATUS:
				if((dwMCIerr=CD_ShowTrackTimes(wDeviceID,szBuffer))!=0L)
					showMCIError(dwMCIerr);
				break;

			// start play at track 1
			case IDM_PLAY:
				if((dwMCIerr=CD_PlayTrack(wDeviceID,1,0))!=0L)
					showMCIError(dwMCIerr);
				else {
					iCDstatus=CD_PLAYING;
					wsprintf(szTitle,"CD (%s) %d",(LPSTR)szStatus[iCDstatus],
						CD_GetCurrentTrack(wDeviceID));
					SetWindowText(hDlg,szTitle);
				}
				break;

			// if the CD is playing, backup one track, else play
			case IDM_BACK:
				if(iCDstatus==CD_PLAYING) {
					if((dwMCIerr=CD_ChangeTrack(wDeviceID,-1))!=0L)
						showMCIError(dwMCIerr);
				} else SendMessage(hDlg,WM_COMMAND,IDM_PLAY,0L);
				break;

			// if the CD is playing, forward one track, else play
			case IDM_FORWARD:
				if(iCDstatus==CD_PLAYING) {
					if((dwMCIerr=CD_ChangeTrack(wDeviceID,1))!=0L)
						showMCIError(dwMCIerr);
				} else SendMessage(hDlg,WM_COMMAND,IDM_PLAY,0L);
				break;

			// if the CD is playing, pause it, else resume play
			case IDM_PAUSE:
				if(iCDstatus==CD_PLAYING) {
					if((dwMCIerr=CD_Pause(wDeviceID))!=0L)
						showMCIError(dwMCIerr);
					else iCDstatus=CD_PAUSED;
				} else
					SendMessage(hDlg,WM_COMMAND,IDM_RESUME,0L);
				break;

			// if the CD is paused, resume play (play at current location)
			case IDM_RESUME:
				if(iCDstatus==CD_PAUSED || iCDstatus==CD_STOPPED) {
					if((dwMCIerr=CD_ResumePlay(wDeviceID))!=0L)
						showMCIError(dwMCIerr);
					else {
						iCDstatus=CD_PLAYING;
						wsprintf(szTitle,"CD (%s) %d",(LPSTR)szStatus[iCDstatus],
							CD_GetCurrentTrack(wDeviceID));
						SetWindowText(hDlg,szTitle);
					}
				}
				break;

			// if the CD is playing or pause, stop it
			case IDM_STOP:
				if(iCDstatus==CD_PLAYING || iCDstatus==CD_PAUSED) {
					if((dwMCIerr=CD_Stop(wDeviceID))!=0L)
						showMCIError(dwMCIerr);
					else iCDstatus=CD_STOPPED;
				}
				break;

			// untested (mine doesn't support) toggle door open/closed
			case IDM_EJECT:
				if(iCDstatus!=CD_OPEN) {
					if((dwMCIerr=CD_Open(wDeviceID))!=0L)
						showMCIError(dwMCIerr);
					else iCDstatus=CD_OPEN;
				} else if((dwMCIerr=CD_Close(wDeviceID))!=0L)
						showMCIError(dwMCIerr);
					else iCDstatus=CD_STOPPED;
				break;

			// this is a test routine (activated by non-visible button)
			case IDM_SHVOL:
				uAUXerr=auxGetVolume(wDeviceID,(LPDWORD)&volume);
				wsprintf(szBuf,"E:%u VL:%d VH:%d",uAUXerr,
					LOWORD(volume),HIWORD(volume));
                MessageBox(hDlg,szBuf,"CD Volume",MB_OK);
                break;

			// brag routine (actived by non-visible button)
			case IDM_SHAUTH:
				MessageBox(hDlg,
				"Created by John A. Junod\nzj8549@trotter.usma.edu",
				"CD Author",MB_OK);
				break;

			// if they select close, turn off the timer and exit
			case IDCANCEL:
				KillTimer(hDlg,1);
				EndDialog(hDlg,NULL);
				return(TRUE);
			default:
				return(DefWindowProc(hDlg,message,wParam,lParam));
		  }
		  return(TRUE);

		case WM_CLOSE:
			KillTimer(hDlg,1);
			break;
	}
	return(FALSE);
}

// use mciGetErrorString to display error
void showMCIError(DWORD dwError) {
	char szErrorBuf[MAXERRORLENGTH];

	MessageBeep(MB_ICONEXCLAMATION);
	if(mciGetErrorString(dwError,(LPSTR)szErrorBuf,MAXERRORLENGTH))
		MessageBox(hMainWnd,szErrorBuf,"MCI Error",MB_ICONEXCLAMATION);
	else
		MessageBox(hMainWnd,"Unknown Error","MCI Error",MB_ICONEXCLAMATION);
}
