Click here to Skip to main content
Licence GPL3
First Posted 8 Dec 2003
Views 162,798
Bookmarked 81 times

A Basic Media Player

By | 8 Dec 2003 | Article
Using MCIWnd wrapper class to write a simple media player

Sample Image - hmediaplayer.jpg

Introducting MCIWnd Window Class

MCIWnd is a window class for controlling multimedia devices. A library of functions, messages, and macros associated with MCIWnd provides a simple method to add multimedia playback or recording capabilities to your applications.

The MCIWnd Window class is very easy to use. By identifying a simple HWND member variable and assigning it to MCI window using a single function, you can create a control that plays any device that uses the media control interface (MCI) and gain support of any installed codec on your machine. These devices include Audio CDs, WAV Audios, MIDIs, and video devices with any supported codec.

Automating playback is also quick and easy. Using only one function and two macros, an application can create an MCIWnd window with the appropriate media device, play the device, and close both the device and the window when the content has finished playing.

Note that term device refers to any playable media from file stored to any playable medium.

Note: to use MCIWnd Class in your application you must add vfw32.lib library to Link sections of Project Settings (accessible by Ctrl+F7) or simply add following line your header:

#pragma comment(lib, "vfw32.lib")

which does the same.

Considering we want to write a dialog based player, after adding library, add a HWND member variable to your dialog class (as mentioned above), for example:

HWND m_Player;

Then, add following code to any section you want to open your media for playing:

m_Player = MCIWndCreate(GetSafeHwnd(),AfxGetInstanceHandle(),
    WS_CHILD | WS_VISIBLE, m_sFileName);

Where m_sFileName is a member variable which holds media name. After that you can use single line macros to control media playback. e.g. MCIWndPlay(m_Player) to start media playback or MCIWndStop(m_Player).

You are done, you have a media player now!

A wrapper class for MCIWnd: CEasyPlayer

I have written a very simple wrapper class for this API. This wrapper class is part of my work. That certain program needed simple playback of wav and mp3 media and sometimes continuous playing (loop). So, I just wrapped very few macros and messages in implementing the class. The class interface is as below:

class CEasyPlayer : public CWnd
{
public:
CEasyPlayer();
CEasyPlayer(HWND hwParent);

public:
HWND hwndParent;

public:
long lPos;
void Rwd();
void Fwd();
void DecreaseVolume();
void IncreaseVolume();
long GetVolume();
long lVolume;
void SetVolume(long lVol);
long GetLength();
long GetPosition();
void SetPosition(long lPos);
HWND GetWindowHandle();
void Resume();
void Kill();
void Break();
void Loop();
void Close();
HWND Initialize();
void Play();
void Stop();
void Pause();
long GetMode();
CString GetPath();
void SetPath(CString sPath);
void SetParent(HWND hParent);
HWND GetParent();
virtual ~CEasyPlayer();

protected:
HWND c_Player;
CEvent m_Event;
CString m_sPath;

//{{AFX_MSG(CEasyPlayer)
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

c_Player is that so called HWND member variable. I use c_ prefix to determine control variables from other member variables(Values). Initialize() creates MCIWnd control and assigns it to c_Player. Other functions are identify themselves by their names which show exact duty of function. It is necessary to mention that GetMode() is used to determine playback status and returns one of following values:

Operating mode MCI constant
not ready MCI_MODE_NOT_READY
open MCI_MODE_OPEN
paused MCI_MODE_PAUSE
playing MCI_MODE_PLAY
recording MCI_MODE_RECORD
seeking MCI_MODE_SEEK
stopped MCI_MODE_STOP

Class code is clear, it just wraps some macros, passes values to them and gets results from them. The only part of code that may need description is Loop() function. Using Loop() will cause launching a thread call to LoopThread() which implementation is as follows:

UINT LoopThread(LPVOID pParam)
{
    CParams* pParameters;
    pParameters=(CParams*)pParam;

    CEasyPlayer* pWnd=(CEasyPlayer*)pParameters->pWnd;
    CEvent* pEvent=(CEvent*)pParameters->pEvent;
    HWND c_Player=(HWND)pParameters->hWnd;

    while(WaitForSingleObject(pEvent->m_hObject,5)==WAIT_TIMEOUT)
    {
        if (pWnd->GetMode()==MCI_MODE_STOP)
            ::PostMessage(c_Player, MCI_PLAY, 0, 0);
    }
    return 0;
}

A conditional loop which checks if m_Event member variable of class is set, if not then checks if media playback stoped. If so then replys the media by sending a MCI_PLAY message to HWND control. Very simple!

Hasti Media Player

After concluding that project, I decided to try writing a Media Player, and that'is it. Using potentials of CStatic control as a CWnd derived class, I made a GUI for my wrapper class. I used a CStatic control to hold onto video media playback (if exist). This CStatic control rules as CEasyPlayer instance parent.

Changing approach this application did not used Loop() member function for continuous media playback. Instead a timer used to periodically check if media stopped or not.

I must mention that I used Nishant S approach to handles key board messages and menu accelerators in this application. Thank you very much Nishant S.

This application is dedicated to my Hasti.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

M. Bonvari

Other

Iran (Islamic Republic Of) Iran (Islamic Republic Of)

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralProblem with MCIWndGetPosition(c_Player); PinmemberJames86XXX3:27 3 Oct '09  
GeneralMCIWndOpen() Pinmemberzhang lu0:31 12 Apr '09  
Generalwhy lVol=rs.GetSettingsVolume()can not get correct result Pinmemberzjutyujf22:10 16 Mar '09  
GeneralMemory Leak PinmemberAmir Dashti20:21 8 Nov '08  
QuestionMedia player interface Pinmemberboyooyo4:56 22 Sep '08  
GeneralMedia Player Pinmemberjmahesh20:45 20 Aug '08  
QuestionmyPlayer.Play(), video plays very fast Pinmembereverton9:32 19 Aug '08  
QuestionHow to catch the popup window? Pinmemberzhang lu23:28 25 Jul '07  
QuestionCan I draw over the same window? PinmemberIgnacio Brana16:32 23 May '07  
Questionpros and cons PinmemberNasreen.n.m19:23 4 Dec '06  
AnswerRe: pros and cons [modified] Pinmembertanvon malik17:40 21 Nov '07  
Questiondirectshow PinmemberNasreen.n.m19:19 4 Dec '06  
AnswerRe: directshow Pinmembertanvon malik17:35 21 Nov '07  
QuestionGet Position and Set Flag PinmemberYousuf Taufiq2:47 19 Jul '06  
Generalbad error Pinmemberlaserbeak4310:40 30 May '06  
GeneralRe: bad error PinmemberM. Bonvari19:04 30 May '06  
Generalset volume could not work Pinmemberzhangshsy14:44 9 Feb '06  
GeneralRe: set volume could not work Pinmemberzhangshsy15:27 9 Feb '06  
GeneralVideo Display Problem PinmembereVideoEuthusiast20:02 5 Feb '06  
GeneralRe: Video Display Problem Pinmemberkezhu16:07 3 Apr '06  
GeneralRe: Video Display Problem Pinmemberkezhu16:21 3 Apr '06  
GeneralRe: Video Display Problem Pinmemberkezhu15:13 6 Apr '06  
Hello:
First many thanks to the author for sharing the codes with us though some problems arise on different platforms. These codes are very helpful for me to understand and program my own media player.
 
Notice: It will be your own risk to use the codes below.
 
Some lines of codes need to be added to solve this problems.
 
1. Add Realize() to CEasyPlayer
void CEasyPlayer::Realize(BOOL fBkgnd)
{
MCIWndRealize( c_Player, fBkgnd );
}
 

2. Add some lines to OnPaint() in CmciDlg
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{// line added here
CRect rect;
m_ctrlMovie.GetWindowRect(&rect);
m_ctrlMovie.InvalidateRect (&rect, FALSE);
m_ctrlMovie.UpdateWindow();
 
myPlayer.Realize(FALSE);
// line added above
CDialog::OnPaint();
}
 
3. for the full screen mode
3.1 add OnPaint() to the class then
3.2 add some lines as above to the OnPaint()
void CFullMovie::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect rect;
this->GetWindowRect(&rect);
this->InvalidateRect (&rect, TRUE);
this->UpdateWindow();
ep.Realize(TRUE);
// warning: CDialog::OnPaint() has to be added, I don't know why. If not added
// some funny thing would happen.
CDialog::OnPaint() ;
// Do not call CDialog::OnPaint() for painting messages
}
 
Wish the above codes are helpful. As I am a stand along programmer learning by self taught, I might not be able to answer your questions if they are too hard.
 
Cheers,
 
Ke

GeneralRe: Video Display Problem PinmemberJoseph Sid Faris10:51 13 Aug '06  
GeneralRe: Video Display Problem Pinmemberkezhu15:45 16 Aug '06  
GeneralSolution to Re:Video Display Problem PinmemberAttila F19:21 9 Nov '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120529.1 | Last Updated 9 Dec 2003
Article Copyright 2003 by M. Bonvari
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid