Main.cpp

 /*****************************************************

  Mindstorm MP3 Player

  Date: 7/28/06
  Author: Brandon Sachtleben
  Description: Very simple MP3 player. This is my first
   time working with audio, so although it's
   not perfect, it was just fun for me to
   mess with. I'm sure there are better methods
   than what I used. I wrote the whole thing in
   about an hour or less, so excuse the messy
   code :-).
   Feel free to use the code for
   whatever you want and give any feedback
   you have.

*****************************************************/

////// Includes
#include <windows.h>
#include <mmsystem.h>
#include <commctrl.h>
#include <stdio.h>
#include <vector>
#include "resource.h"

////// Globals
HWND hWnd = NULL;
HWND hPlay = NULL;
HWND hStop = NULL;
HWND hPause = NULL;
HWND hOpen = NULL;
HWND hProgress = NULL;
HANDLE hBitmap = NULL;
HDC dcSkin = NULL;
BOOL bDone = FALSE;
BOOL bRegioned = TRUE;
int Status = 0;
int ScreenWidth = 341;
int ScreenHeight = 263;
POINT curpoint, point;
RECT MainRect, rect;
HINSTANCE hInst;
MCIDEVICEID pDevice = 0;
MCI_OPEN_PARMS op;
char lastFile[256];
char Title[256];
char Time[256];
char szFileTitle[300];
int hours, minutes, seconds;
int rSeconds;

////// Prototypes
LRESULT CALLBACK WndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
void SkinMe(HDC dc);
void RegionMe();
void ShowMessage( const char *Text, const char *Title, ... );
void ShowMessage( const char *Text, ... );
void PlayAudio( const char *Filename );
void PauseAudio();
void StopAudio();

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
WNDCLASSEX wc;
MSG Msg;

wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)GetStockObject( DKGRAY_BRUSH );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hIconSm = LoadIcon( NULL, IDI_WINLOGO );
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "AUDIOPLAYER";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;

// Register window class
RegisterClassEx( &wc );

// Create the window
int x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (ScreenWidth / 2);
int y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (ScreenHeight / 2);
hWnd = CreateWindowEx( NULL, "AUDIOPLAYER", "Audio Player", WS_OVERLAPPEDWINDOW,
x, y, ScreenWidth, ScreenHeight, NULL, NULL, hInstance, NULL );
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );

HBITMAP hSkinBmp = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_SKIN ));
dcSkin = CreateCompatibleDC(0);
HBITMAP hOldBmp = (HBITMAP)SelectObject( dcSkin, hSkinBmp );
RegionMe();

hInst = hInstance;

// Set timer
DWORD lastTime = GetTickCount() * 0.001f;
DWORD curTime;

// Progress bar
INITCOMMONCONTROLSEX InitCtrlEx;

InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
InitCommonControlsEx(&InitCtrlEx);

// set timer rect
rect.left = 10;
rect.right = 320;
rect.top = 50;
rect.bottom = 100;

while( !bDone )
{
// not necessarily the best of way of doing this but it works
if(Status == 1)
{
if( ::PeekMessage(&Msg, hWnd, NULL, NULL, PM_NOREMOVE) )
{
if(GetMessage( &Msg, hWnd, NULL, NULL ))
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
}

curTime = GetTickCount() * 0.001f;
if( curTime - lastTime >= 1 ) // 1 second
{
SendMessage(hProgress, PBM_SETSTEP, 1, 0);
SendMessage(hProgress, PBM_STEPIT, 0, 0);
if(seconds == 1 && minutes == 0 && hours == 0)
{ // song is done
sprintf( Title, "Stopped: %s", szFileTitle );
StopAudio();
SendMessage(hProgress, PBM_SETPOS, 0, 0);
Status = 0;
}
if(seconds != 0)
seconds--; // subtract 1 second
else {
minutes--;
seconds = 59; // reset
}
sprintf(Time, "%02d:%02d:%02d", hours, minutes, seconds); // update time
InvalidateRect(hWnd, &rect, TRUE);
lastTime = curTime;
}
}
else
{
if(GetMessage( &Msg, hWnd, NULL, NULL ))
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
}
}

return Msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
switch( Msg )
{
case WM_CREATE:
hPlay = CreateWindow( "BUTTON", "Play", WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
10, 200, 35, 35, hWnd, NULL, hInst, NULL );
hPause = CreateWindow( "BUTTON", "Pause", WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
45, 200, 35, 35, hWnd, NULL, hInst, NULL );
hStop = CreateWindow( "BUTTON", "Stop", WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
80, 200, 35, 35, hWnd, NULL, hInst, NULL );
hOpen = CreateWindow( "BUTTON", "Open", WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
296, 200, 35, 35, hWnd, NULL, hInst, NULL );

hBitmap = LoadImage (GetModuleHandle (NULL), "Images/play_button.bmp",
IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
SendMessage(hPlay, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,
(LPARAM)(HANDLE) hBitmap);

hBitmap = LoadImage (GetModuleHandle (NULL), "Images/pause_button.bmp",
IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
SendMessage(hPause, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,
(LPARAM)(HANDLE) hBitmap);

hBitmap = LoadImage (GetModuleHandle (NULL), "Images/stop_button.bmp",
IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
SendMessage(hStop, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,
(LPARAM)(HANDLE) hBitmap);

hBitmap = LoadImage (GetModuleHandle (NULL), "Images/open_button.bmp",
IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
SendMessage(hOpen, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,
(LPARAM)(HANDLE) hBitmap);

hProgress = CreateWindowEx(NULL, PROGRESS_CLASS, NULL,
PBS_SMOOTH | WS_CHILD | WS_VISIBLE,
120, 200, 171, 35,
hWnd, NULL, hInst, NULL);
SendMessage(hProgress, PBM_SETBARCOLOR, 0, (COLORREF)RGB(20, 95, 190));
SendMessage(hProgress, PBM_SETBKCOLOR, 0, (COLORREF)RGB(210, 230 , 255));
break;

case WM_COMMAND:
if ((HWND)lParam == hPlay && HIWORD(wParam) == BN_CLICKED)
{
// Play audio file
if(!strcmp(lastFile, "")) return 0;
sprintf( Title, "Playing: %s", szFileTitle );
InvalidateRect(hWnd, &rect, TRUE);
if(Status == 0) { // if not playing, play audio
PlayAudio( lastFile );
Status = 1;
}
if(Status == 2) { // if paused, resume
mciSendCommand( pDevice, MCI_RESUME, 0, NULL );
Status = 1;
}
}

if ((HWND)lParam == hPause && HIWORD(wParam) == BN_CLICKED)
{
// Pause audio file
if(!strcmp(lastFile, "")) return 0;
sprintf( Title, "Paused: %s", szFileTitle );
InvalidateRect(hWnd, &rect, TRUE);
PauseAudio();
Status = 2;
}

if ((HWND)lParam == hStop && HIWORD(wParam) == BN_CLICKED)
{
// Stop audio file
if(!strcmp(lastFile, "")) return 0;
sprintf( Title, "Stopped: %s", szFileTitle );
InvalidateRect(hWnd, &rect, TRUE);
StopAudio();
Status = 0;
SendMessage(hProgress, PBM_SETPOS, 0, 0);
}

if ( (HWND) lParam == hOpen && HIWORD(wParam) == BN_CLICKED)
{
// Open a file
TCHAR szFile[MAX_PATH] = { 0 };

TCHAR *szFilter =TEXT("MP3 Files(*.mp3)\0")
TEXT("*.mp3\0");

// Query the current folder
TCHAR szCurDir[MAX_PATH];
::GetCurrentDirectory(MAX_PATH-1,szCurDir);

OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetParent(hWnd);
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrTitle = TEXT("Open");
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = 300;
ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER;
if (GetOpenFileName(&ofn))
{
if(Status == 1)
{
StopAudio();
Status = 0;
}
SendMessage(hProgress, PBM_SETPOS, 0, 0);

// Try to open the file (which must exist)
HANDLE hFile = CreateFile(ofn.lpstrFile, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);

// On failure CreateFile returns -1
if (hFile == (HANDLE)-1)
{
MessageBox(NULL,"Could not open this file", "File I/O Error", MB_ICONSTOP);
return FALSE;
}

ZeroMemory(Title, sizeof(Title));
sprintf( Title, "Playing: %s", szFileTitle );

// Play the file
PlayAudio( ofn.lpstrFile );
Status = 1;
}
}
break;

case WM_LBUTTONDOWN:
SetCapture( hWnd );
GetWindowRect(hWnd, &MainRect);
     
//save current cursor coordinate
GetCursorPos(&point);
    
ScreenToClient(hWnd, &point);

// Minimize button
if(point.x >= 275 && point.x <= 287)
{
if(point.y >= 8 && point.y <= 20)
{
ShowWindow( hWnd, SW_MINIMIZE );
}
}

// Close window
if(point.x >= 311 && point.x <= 324)
{
if(point.y >= 8 && point.y <= 20)
{
SendMessage( hWnd, WM_CLOSE, 0, 0 );
}
}
break;

case WM_LBUTTONUP:
ReleaseCapture();
break;

case WM_MOUSEMOVE:
GetCursorPos(&curpoint);

if(wParam==MK_LBUTTON)
{
MoveWindow(hWnd, curpoint.x - point.x, curpoint.y - point.y,
MainRect.right - MainRect.left, MainRect.bottom - MainRect.top, 
TRUE);
}
break;

case WM_PAINT:
PAINTSTRUCT ps;
BeginPaint(hWnd,&ps);

// blit the skin
if (bRegioned) SkinMe(ps.hdc);

SetBkMode( ps.hdc, TRANSPARENT );
TextOut( ps.hdc, 10, 55, Title, 45 );
TextOut( ps.hdc, 10, 70, Time, strlen(Time) );

EndPaint(hWnd,&ps);
break;

case WM_DESTROY:
bDone = TRUE;
PostQuitMessage( 0 );
break;
}

return DefWindowProc( hWnd, Msg, wParam, lParam );
}

void SkinMe(HDC dc)
{
  BitBlt(dc, 0,0,ScreenWidth-4,ScreenHeight, dcSkin, 0,0, SRCCOPY);
}

void RegionMe()
{
  HRGN hRegion1 = CreateEllipticRgn(-59,-59,ScreenWidth+59,ScreenHeight+59);

  SetWindowRgn(hWnd, hRegion1, true);

  DeleteObject(hRegion1);

  DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
  dwStyle &= ~(WS_CAPTION|WS_SIZEBOX);
  SetWindowLong(hWnd, GWL_STYLE, dwStyle);

  // Repaint
  InvalidateRect(hWnd, NULL, TRUE);
  SetWindowPos(hWnd, NULL, 0,0,ScreenWidth-1,ScreenHeight-1, SWP_NOMOVE|SWP_NOZORDER);

  bRegioned = true;
}

void PlayAudio( const char *Filename )
{
if(Status == 1) return;

op.dwCallback = 0;
op.lpstrDeviceType = (char*)MCI_ALL_DEVICE_ID;
op.lpstrElementName = Filename;
op.lpstrAlias = 0;

// Send command
if ( mciSendCommand( 0, MCI_OPEN,
MCI_OPEN_ELEMENT | MCI_WAIT,
(DWORD)&op) == 0)
{
// Success on open
pDevice = op.wDeviceID;
}
else
{
// Failed
}

MCI_PLAY_PARMS pp;
pp.dwCallback = 0;

if(Status == 0)
{
strcpy( lastFile, Filename );
char szCommandBuffer[512] = {char()}, szReturnBuffer[32] = {char()};

::sprintf(szCommandBuffer, "open "%s" alias myfile", Filename);

DWORD dwDummy = ::mciSendString(szCommandBuffer, NULL, NULL, NULL);

if(!dwDummy)
{
::sprintf(szCommandBuffer, "status myfile length", Filename);
dwDummy = ::mciSendString(szCommandBuffer, szReturnBuffer, sizeof(szReturnBuffer), NULL);


::mciSendString(szCommandBuffer, NULL, NULL, NULL);
}

if(dwDummy) { }

rSeconds = atoi(szReturnBuffer)/1000;
SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, rSeconds));
float nSecond = atof(szReturnBuffer)/1000/60;
seconds = (int)nSecond;
nSecond -= seconds;
seconds = nSecond * 60;
hours = atoi(szReturnBuffer)/1000/60/60;
minutes = atoi(szReturnBuffer)/1000/60;

sprintf(Time, "%02d:%02d:%02d", hours, minutes, seconds);
InvalidateRect(hWnd, &rect, TRUE);
}

mciSendCommand(pDevice, MCI_PLAY, MCI_NOTIFY, (DWORD)&pp);
}

void PauseAudio()
{
mciSendCommand( pDevice, MCI_PAUSE, 0, NULL );
}

void StopAudio()
{
mciSendCommand( pDevice, MCI_STOP, 0, NULL );
mciSendCommand( pDevice, MCI_CLOSE, 0, 0 );
mciSendString( "close myfile", 0, 0, 0);
}

Project Homepage: