本篇是创建游戏内核(21)【OO改良版】的续篇,关于该内核的细节说明请参阅创建游戏内核(22)。
接口:
//======================================================================================
// This class encapsulates mp3 playing.
//======================================================================================
typedef class MP3
{
public:
MP3();
~MP3();
BOOL init();
void shutdown();
BOOL render_file(const char* filename);
BOOL play();
BOOL stop();
BOOL pause();
BOOL is_playing();
private:
IGraphBuilder* m_graph_builder;
IMediaControl* m_media_control;
IMediaEvent* m_media_event;
} *MP3_PTR;
实现:
//------------------------------------------------------------------------------
// Constructor, zero member data.
//------------------------------------------------------------------------------
MP3::MP3()
{
memset(this, 0, sizeof(*this));
}
//------------------------------------------------------------------------------
// Destructor, release resource.
//------------------------------------------------------------------------------
MP3::~MP3()
{
shutdown();
}
//------------------------------------------------------------------------------
// Release all resource which used to play mp3.
//------------------------------------------------------------------------------
void MP3::shutdown()
{
release_com(m_media_event);
release_com(m_media_control);
release_com(m_graph_builder);
CoUninitialize();
}
//------------------------------------------------------------------------------
// Create graph builder, query interface for medial control and medial event.
//------------------------------------------------------------------------------
BOOL MP3::init()
{
// shutdown prior initialized system
shutdown();
// initialize com
CoInitialize(NULL);
// create graph builder object and media controls
if(FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
(void**)&m_graph_builder)))
{
return FALSE;
}
m_graph_builder->QueryInterface(IID_IMediaControl, (void**) &m_media_control);
m_graph_builder->QueryInterface(IID_IMediaEvent, (void**) &m_media_event);
return TRUE;
}
//------------------------------------------------------------------------------
// Builds a filter graph that renders the specified file.
//------------------------------------------------------------------------------
BOOL MP3::render_file(const char* filename)
{
// error checking
if(m_graph_builder == NULL || m_media_control == NULL)
return FALSE;
// stop the current song
m_media_control->Stop();
// convert filename to wide-character string
WCHAR _w_filename[MAX_PATH];
mbstowcs(_w_filename, filename, MAX_PATH);
// builds a filter graph that renders the specified file
if(FAILED(m_graph_builder->RenderFile(_w_filename, NULL)))
return FALSE;
return TRUE;
}
//------------------------------------------------------------------------------
// Play mp3.
//------------------------------------------------------------------------------
BOOL MP3::play()
{
// error checking
if(m_media_control == NULL)
return FALSE;
// Runs all the filters in the filter graph.
// While the graph is running, data moves through the graph and is rendered.
if(FAILED(m_media_control->Run()))
return FALSE;
return TRUE;
}
//------------------------------------------------------------------------------
// Stop playing mp3.
//------------------------------------------------------------------------------
BOOL MP3::stop()
{
// error checking
if(m_media_control == NULL)
return FALSE;
// stops all the filters in the graph
if(FAILED(m_media_control->Stop()))
return FALSE;
return TRUE;
}
//------------------------------------------------------------------------------
// Pause playing mp3.
//------------------------------------------------------------------------------
BOOL MP3::pause()
{
// error checking
if(m_media_control == NULL)
return FALSE;
// pause all the filters in the filter graph
if(FAILED(m_media_control->Pause()))
return FALSE;
return TRUE;
}
//------------------------------------------------------------------------------
// Ascertain whether mp3 has completed playing.
//------------------------------------------------------------------------------
BOOL MP3::is_playing()
{
// error checking
if(m_media_event == NULL)
return FALSE;
// get event and handle it
long _event, _param1, _param2;
// retrieves the next event notification from the event queue
m_media_event->GetEvent(&_event, &_param1, &_param2, 1);
if(_event == EC_COMPLETE)
{
// free resources associated with the paramters of an event
m_media_event->FreeEventParams(_event, _param1, _param2);
return TRUE;
}
m_media_event->FreeEventParams(_event, _param1, _param2);
return FALSE;
}
测试代码:
/*****************************************************************************
PURPOSE:
Test for class MP3.
*****************************************************************************/
#include "core_common.h"
#include "core_framework.h"
#include "core_sound.h"
class APP : public FRAMEWORK
{
public:
BOOL init()
{
m_mp3.init();
if(m_mp3.render_file("song.mp3"))
m_mp3.play();
while(m_mp3.is_playing())
;
return TRUE;
}
BOOL frame()
{
return TRUE;
}
BOOL shutdown()
{
return TRUE;
}
private:
MP3 m_mp3;
};
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
if(! build_window(inst, "mp3_class", "mp3_test", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480))
return -1;
app.run();
return 0;
}