//========================================================================

//TITLE:

//    CMedia更新至v1.4.3

//AUTHOR:

//    norains

//DATE:

//    Friday  27-July-2007

//Environment:

//        EVC4.0 + Windows CE 5.0 Standard SDK

//========================================================================


    相对v1.2.0版本进行的改进:

    1.增加GetMediaProperty函数获得的属性,增加如下属性:llDuration,llAvailableEarliest,llAvailableLatest.


    2.增加如下函数:SetRate(),GetRate(),GetPositionCurrent(),SetPositionCurrent() ,GetDisplayMode()


    3.改进之前一些函数的HRESULT值返回BOOL值的判定方法


    4.增加SetVideoWindow()一个参数,以设置可以在窗口的任意位置为起点播放视频


    5.改进SetDisplayMode()函数,当窗口句柄为空时,设置播放区域为0,并返回FALSE


    6.改进SetNotifyWindow()函数,令其能够接收普通的窗口消息


    7.Open()的参数改为const类型,更符合实际意义

 

    我们来看看具体更新了哪些功能:


    1.MEDIAPROPERTY


        增加了llDuration,llAvailableEarliest,llAvailableLatest属性,分别代表影片的时间长度,最早的可拖拽的时间位置,最早的可拖拽的时间位置.这个属性可以用在GetMediaProperty()函数中.




    2.SetRate(),GetRate()


        SetRate()设置当前的播放速率,"1"为正常速率,"2"即为两倍速,以此类推.


        GetRate()获取当前播放的速率.




    3.GetPositionCurrent(),SetPositionCurrent()


        GetPositionCurrent():获取当前的时间位置,返回的时间值以100ns为基本单位.   

        SetPositionCurrent():设置播放的时间位置,该范围必须是llAvailableEarliest和llAvailableLatest之间的数值.




    4.GetDisplayMode()


         该函数用来获取当前的播放模式.



    v1.4.3的完整代码如下:


///////////////////////////////////////////////////////////////////////

//Media.h: interface for the CMedia class.

//

//Version:

//    1.4.3

//Date:

//    2007.07.19

//////////////////////////////////////////////////////////////////////

#ifndef MEDIA_H

#define    MEDIA_H



#include <mmsystem.h>

#include <streams.h>


//--------------------------------------------------------------------

//Macro define


//The volume value

#define MAX_VOLUME                    0

#define MIN_VOLUME                    -10000


//The balance value

#define MAX_BALANCE                    10000

#define MIN_BALANCE                    -10000


//The flag means that the area is the whole window 

const RECT RC_WHOLE_WINDOWN_AREA = {0,0,0,0};            


//--------------------------------------------------------------------

//Enum value


enum DISPLAYMODE

{    

    //Fit to the play window size. How wide (height) the window is, how 

    //is the move. Keep aspect ratio.

    DISP_FIT,


    //Not support.Stretch to the play window size. Don't keep the aspect ratio.

    DISP_STRETCH,


    //Full screen play.

    DISP_FULLSCREEN,


    //When the size of video is smaller than the play window, it displayes

    //as the video size. If it's bigger , it just like the DISP_FIT mode.

    DISP_NATIVE

};

//--------------------------------------------------------------------


//The media file property

typedef struct

{


    //The volume range is –10,000 to 0.

    //Divide by 100 to get equivalent decibel value (for example –10,000 = –100 dB). 

    LONG lVolume;



    //The value from –10,000 to 10,000 indicating the stereo balance

    //As with the Volume property, units correspond to .01 decibels (multiplied by –1 when plBalance is a positive value).

    //For example, a value of 1000 indicates –10 dB on the right channel and –90 dB on the left channel. 

    LONG lBalance;



    //Width of the video  

    LONG lWidth;



    //Height of the video

    LONG lHeight;



    //Approximate bit rate

    LONG lBitRate;


    //The length of time that the media stream will play.

    //The duration assumes normal playback speed, and it is therefore unaffected by the rate

    LONGLONG llDuration;



    //Earliest time that can be efficiently seeked to. 

    LONGLONG llAvailableEarliest;


    //Latest time that can be efficiently seeked to

    LONGLONG llAvailableLatest;


}MEDIAPROPERTY,*PMEDIAPROPERTY;

//--------------------------------------------------------------------

class CMedia  

{

public:

    DISPLAYMODE GetDisplayMode();

    BOOL SetPositionCurrent(LONGLONG llPos);

    BOOL GetPositionCurrent(LONGLONG *pllPos);

    BOOL GetRate(double *pdRate);

    BOOL SetRate(double dRate);

    BOOL GetEvent(LONG *plEvCode, LONG *plParam1, LONG *plParam2);

    BOOL SetNotifyWindow(HWND hWnd, UINT wMsg,long lInstanceData);

    BOOL SetVolume(LONG lVolume, LONG lBalance = 0);

    BOOL SetDisplayMode(DISPLAYMODE mode);

    BOOL GetMediaProperty(PMEDIAPROPERTY pOutProperty);

    static CMedia * GetInstance();

    void Close();

    BOOL CheckVisibility();

    BOOL SetVideoWindow(HWND hWndVideo,const RECT &rcDisp = RC_WHOLE_WINDOWN_AREA);

    BOOL Open(const TCHAR *pcszFileName);

    BOOL Stop();

    BOOL Pause();

    BOOL Play();

    virtual ~CMedia();


protected:



    CMedia();


    // Collection of interfaces

    IGraphBuilder *m_pGB;

    IMediaControl *m_pMC;

    IMediaEventEx *m_pME;

    IVideoWindow  *m_pVW;

    IBasicAudio   *m_pBA;

    IBasicVideo   *m_pBV;

    IMediaSeeking *m_pMS;


    TCHAR m_szFileName[MAX_PATH];

    HWND m_hWndVideo; //The window play video

    HWND m_hWndNotify; //The window notify

    BOOL m_bExitThrd;

    BOOL m_bThrdRunning;

    static CMedia * m_pInstance;

    DISPLAYMODE m_DispMode;

    DWORD m_dwCapability;

    RECT m_rcDisp;

};


#endif //#ifndef MEDIA_H



///////////////////////////////////////////////////////////////////////

// Media.cpp: implementation of the CMedia class.

//

//////////////////////////////////////////////////////////////////////


#include "stdafx.h"

#include "Media.h"




//========================================================================================================

//Link the .lib

//The lib also is copy from "(InstallDir)WINCE500PUBLICDIRECTXSDKLIB"


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


#ifdef CPU_X86EM

    #pragma comment (lib,"./lib/X86em/Strmiids.lib")

    #pragma comment (lib,"./lib/X86em/Strmbase.lib")

#endif


#ifdef CPU_MIPSII

    #pragma comment (lib,"./lib/MIPSII/Strmiids.lib")

    #pragma comment (lib,"./lib/MIPSII/Strmbase.lib")

#endif


#ifdef CPU_ARM4I

    #pragma comment (lib,"./lib/ARM4I/Strmiids.lib")

    #pragma comment (lib,"./lib/ARM4I/Strmbase.lib")

#endif

//========================================================================================================


//----------------------------------------------------------------------------------------------

//Macro define


//Default play mode

#define DEFAULT_DISPLAY_MODE        DISP_NATIVE


//----------------------------------------------------------------------

//Initialize

CMedia *CMedia::m_pInstance = NULL;

//------------------------------------------------------------------------



//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////


CMedia::CMedia():

m_pGB(NULL),

m_pMC(NULL),

m_pME(NULL),

m_pVW(NULL),

m_pBA(NULL),

m_pBV(NULL),

m_pMS(NULL),

m_hWndVideo(NULL),

m_bExitThrd(TRUE),

m_bThrdRunning(FALSE),

m_DispMode(DEFAULT_DISPLAY_MODE),

m_hWndNotify(NULL),

m_rcDisp(RC_WHOLE_WINDOWN_AREA)

{

    memset(m_szFileName,0,sizeof(m_szFileName));

}


CMedia::~CMedia()

{

    if(m_pInstance != NULL)

    {

        delete m_pInstance;

        m_pInstance = NULL;

    }


}





//------------------------------------------------------------

//Description:

//    Play the media file

//    When you call the function,you should call Open() before.

//

//-------------------------------------------------------------

BOOL CMedia::Play()

{    

    // Run the graph to play the media file


    if(m_pMC == NULL)

    {

        return FALSE;

    }





    return SUCCEEDED(m_pMC->Run());


}





//------------------------------------------------------------

//Description:

//    Pause. 

//    When you call the function,you should call Open() before.

//

//-------------------------------------------------------------

BOOL CMedia::Pause()

{


    if(m_pMC == NULL)

    {

        return FALSE;

    }


    return SUCCEEDED(m_pMC->Pause());



}





//------------------------------------------------------------

//Description:

//    Stop.

//    When you call the function,you should call Open() before.

//

//-------------------------------------------------------------

BOOL CMedia::Stop()

{


    if(m_pMC == NULL || m_pMS == NULL)

    {

        return FALSE;

    }


    HRESULT hr;

    hr = m_pMC->Stop();    

    SetPositionCurrent(0);    


    return SUCCEEDED(hr);

}





//--------------------------------------------------------------------------

//Description:

//    Open the media file. When succeed in calling the function ,

//you should call the Close() to release the resource

//

//-------------------------------------------------------------------------

BOOL CMedia::Open(const TCHAR *pcszFileName)

{

    BOOL bResult = FALSE;



    if(_tcslen(pcszFileName) >= MAX_PATH)

    {

        goto END;

    }

    else

    {

        _tcscpy(m_szFileName,pcszFileName);


        //Check the file existing

        HANDLE hdFile = CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);

        if(hdFile == INVALID_HANDLE_VALUE)

        {

            //The file doesn't exist

            goto END;

        }

        else

        {

            CloseHandle(hdFile);

        }

    }






    // Initialize COM 

    if(CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK)

    {

        goto END;

    }


    // Get the interface for DirectShow's GraphBuilder

    if(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB) != S_OK)

    {

        goto END;

    }



    // Have the graph construct its the appropriate graph automatically

    if(m_pGB->RenderFile(m_szFileName, NULL) != NOERROR)

    {

        goto END;

    }



    // QueryInterface for DirectShow interfaces

    if(m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC) != NOERROR)

    {

        goto END;

    }

    if(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME) != NOERROR)

    {

        goto END;

    }

    if(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS) != NOERROR)

    {

        goto END;

    }




    // Query for video interfaces, which may not be relevant for audio files

    if(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW) != NOERROR)

    {

        goto END;

    }

    if(m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV) != NOERROR)

    {

        goto END;

    }


    if(CheckVisibility() == FALSE)

    {

        //It just be the audio file, and don't need video filter.


        // Relinquish ownership (IMPORTANT!) after hiding

        if(m_pVW != NULL)

        {

            m_pVW->put_Visible(OAFALSE);

            m_pVW->put_Owner(NULL);

        }


        if(m_pBV != NULL)

        {

            m_pBV->Release();

            m_pBV = NULL;

        }    



        if(m_pVW != NULL)

        {

            m_pVW->Release();

            m_pVW = NULL;

        }

    }



    // Query for audio interfaces, which may not be relevant for video-only files

    if(m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA) != NOERROR)

    {

        goto END;

    }



    //Set play mode

    SetDisplayMode(m_DispMode);


    //Get the capabilities of the media file.

    m_pMS->GetCapabilities(&m_dwCapability);


    bResult = TRUE;


END:    


    if(bResult == FALSE)

    {

        //Release the resource

        Close();

    }


    return bResult;

}





//------------------------------------------------------------

//Description:

//    This method sets an owning parent for the video window. 

//

//Parameters:

//    hWnd : [in] Handle of new owner window. 

//    rcDisp: [in] The display area. If the parameter is not set,

//            it will be set as RC_WHOLE_WINDOWN_AREA which means thai

//            the whole window is for displaying the video.

//

//----------------------------------------------------------

BOOL CMedia::SetVideoWindow(HWND hWndVideo,const RECT &rcDisp)

{

    m_hWndVideo = hWndVideo;


    m_rcDisp = rcDisp;


    if(m_pVW == NULL)

    {

        return FALSE;

    }


    if(FAILED(m_pVW->put_Owner((OAHWND)hWndVideo)))

    {

        return FALSE;

    }


    if(FAILED(m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)))

    {

        return FALSE;

    }


    //Set play mode in order to notify the displayed area

    return SetDisplayMode(m_DispMode);

}




//------------------------------------------------------------

//Description:

//    Check the file visibility

//    When you call the function,you should call Open() before.

//

//Parameters:

//    TRUE: Video

//    FALSE: It's not the video 

//

//------------------------------------------------------------

BOOL CMedia::CheckVisibility()

{



    if (!m_pVW)

    {

        //No VideoWindow interface.  Assuming audio/MIDI file or unsupported video codec

        return FALSE;

    }


    if (!m_pBV)

    {

        //No BasicVideo interface.  Assuming audio/MIDI file or unsupported video codec.

        return FALSE;

    }



    // If this is an audio-only clip, get_Visible() won't work.

    //

    // Also, if this video is encoded with an unsupported codec,

    // we won't see any video, although the audio will work if it is

    // of a supported format.

    long lVisible;

    return SUCCEEDED(m_pVW->get_Visible(&lVisible));


}





//------------------------------------------------------------

//Description:

//    Release the resource which opened in the Open()    

//

//------------------------------------------------------------

void CMedia::Close()

{


    // Relinquish ownership (IMPORTANT!) after hiding

    if(m_pVW != NULL)

    {

        m_pVW->put_Visible(OAFALSE);

        m_pVW->put_Owner(NULL);

    }


    if(m_pMC != NULL)

    {

        m_pMC->Release();

        m_pMC = NULL;

    }


    if(m_pME != NULL)

    {

        m_pME->SetNotifyWindow(NULL,NULL,NULL);


        m_pME->Release();

        m_pME = NULL;

    }


    if(m_pMS != NULL)

    {

        m_pMS->Release();

        m_pMS = NULL;

    }


    if(m_pBV != NULL)

    {

        m_pBV->Release();

        m_pBV = NULL;

    }


    if(m_pBA != NULL)

    {

        m_pBA->Release();

        m_pBA = NULL;

    }


    if(m_pVW != NULL)

    {

        m_pVW->Release();

        m_pVW = NULL;

    }


    if(m_pGB != NULL)

    {

        m_pGB->Release();

        m_pGB = NULL;

    }


    // Finished with COM

    memset(m_szFileName,0,sizeof(m_szFileName));



    CoUninitialize();

}



//------------------------------------------------------------

//Description:

//    Get the instance of object

//

//------------------------------------------------------------

CMedia * CMedia::GetInstance()

{

    if(m_pInstance == NULL)

    {

        m_pInstance = new CMedia();

    }


    return m_pInstance;

}





//------------------------------------------------------------

//Description:

//    Get the media file property.

//    When you call the function,you should call Open() before.

//

//------------------------------------------------------------

BOOL CMedia::GetMediaProperty(PMEDIAPROPERTY pOutProperty)

{


    MEDIAPROPERTY prop = {0};


    if(m_pBA == NULL && m_pBV == NULL && m_pMS == NULL)

    {

        return FALSE;

    }



    //Get the audio property

    if(m_pBA != NULL)

    {

        m_pBA->get_Volume(&prop.lVolume);

        m_pBA->get_Balance(&prop.lBalance);

    }



    //Get the video property

    if(CheckVisibility() == TRUE && m_pBV != NULL)

    {        

        m_pBV->get_BitRate(&prop.lBitRate);

        m_pBV->GetVideoSize(&prop.lWidth,&prop.lHeight);        

    }



    //Get the seeking property

    if(m_pMS != NULL)

    {

        m_pMS->GetDuration(&prop.llDuration);

        m_pMS->GetAvailable(&prop.llAvailableEarliest,&prop.llAvailableLatest);

    }




    *pOutProperty = prop;



    return TRUE;

}



//------------------------------------------------------------

//Description:

//    Set the display mode.

//    When you call the function,you should call SetVideoWindow() before.

//If the parent windows (m_hWndVideo) is NULL, the display area would be set to zero.

//

//------------------------------------------------------------

BOOL CMedia::SetDisplayMode(DISPLAYMODE mode)

{


    if(m_pVW == NULL)

    {

        return FALSE;

    }


    if(m_hWndVideo == NULL)

    {

        m_pVW->put_Left(0);

        m_pVW->put_Top(0);

        m_pVW->put_Width(0);

        m_pVW->put_Height(0);


        return FALSE;

    }


    m_DispMode = mode;


    if(mode == DISP_FULLSCREEN)

    {

        m_pVW->put_FullScreenMode(OATRUE);

    }

    else

    {

        //Restore to the normal mode

        m_pVW->put_FullScreenMode(OAFALSE);


        RECT rcWnd = m_rcDisp;

        if(rcWnd.left == RC_WHOLE_WINDOWN_AREA.left &&

            rcWnd.top == RC_WHOLE_WINDOWN_AREA.top &&

            rcWnd.right == RC_WHOLE_WINDOWN_AREA.right &&

            rcWnd.bottom == RC_WHOLE_WINDOWN_AREA.bottom )

        {

            GetClientRect(m_hWndVideo,&rcWnd);

        }

        LONG lWndWidth = rcWnd.right - rcWnd.left;

        LONG lWndHeight = rcWnd.bottom - rcWnd.top;


        MEDIAPROPERTY prop = {0};

        GetMediaProperty(&prop);



        if(mode == DISP_FIT || mode == DISP_NATIVE)

        {

            LONG lDispLeft,lDispTop,lDispWidth,lDispHeight;


            if(mode == DISP_NATIVE && lWndWidth >= prop.lWidth && lWndHeight >= prop.lHeight)

            {

                lDispLeft = (lWndWidth - prop.lWidth) / 2 + rcWnd.left;

                lDispTop = (lWndHeight - prop.lHeight) / 2 + rcWnd.top;

                lDispWidth = prop.lWidth ;

                lDispHeight = prop.lHeight ;

            }

            else

            {

                if(prop.lWidth * lWndHeight > lWndWidth * prop.lHeight)

                {

                    lDispWidth = lWndWidth;                

                    lDispHeight = (LONG)((float)lDispWidth / (float)prop.lWidth * prop.lHeight);

                    lDispLeft = rcWnd.left;

                    lDispTop = (lWndHeight - lDispHeight) / 2 + rcWnd.top;        

                }

                else if(prop.lWidth * lWndHeight < lWndWidth * prop.lHeight)

                {

                    lDispHeight = lWndHeight;

                    lDispWidth = (LONG)((float)lDispHeight / (float)prop.lHeight * prop.lWidth);

                    lDispLeft = (lWndWidth - lDispWidth) / 2 + rcWnd.left;

                    lDispTop = rcWnd.top;

                }

                else

                {

                    lDispWidth = lWndWidth;                

                    lDispHeight = lWndHeight;

                    lDispLeft = rcWnd.left;

                    lDispTop = rcWnd.top;

                }

            }






            m_pVW->put_Left(lDispLeft);

            m_pVW->put_Top(lDispTop);

            m_pVW->put_Width(lDispWidth);

            m_pVW->put_Height(lDispHeight);

        }

        else if(mode == DISP_STRETCH)

        {


            m_pVW->put_Left(rcWnd.left);

            m_pVW->put_Top(rcWnd.top);

            m_pVW->put_Width(lWndWidth);

            m_pVW->put_Height(lWndHeight);

        }


    }




    return TRUE;

}



//------------------------------------------------------------

//Description:

//    Set the volume.

//    When you call the function,you should call Open() before.

//

//Parameters:

//    lVolume:[in] The volume (amplitude) of the audio signal. 

//            Range is –10,000 to 0.

//    lBalance:[in]  The balance for the audio signal. Default value is 0.

//            The value from –10,000 to 10,000 indicating the stereo balance.

//

//------------------------------------------------------------

BOOL CMedia::SetVolume(LONG lVolume, LONG lBalance)

{

    if(m_pBA == NULL)

    {

        return FALSE;

    }


    if(lVolume < MIN_VOLUME && lVolume > MAX_VOLUME && lBalance < MIN_BALANCE && lBalance > MAX_BALANCE)

    {

        return FALSE;

    }


    m_pBA->put_Volume(lVolume);

    m_pBA->put_Balance(lBalance);


    return TRUE;

}





//----------------------------------------------------------------------

//Description:

//    Registers a window that will handle the notified message when a specified event occurs and some window message

//

//Parameters:

//    hWnd:[in] Handle of window to notify. Pass NULL to stop notification. 

//    wMsg:[in] Window message to be passed as the notification. 

//    lInstanceData:[in] Value (instance data) to be passed as the lParam parameter for the lMsg message.

//

//Remarks:

//    When the notified window receive the wMsg as the notification, you could get the event code.

//    The follow codes show that process:

//

//        //"WM_GRAPHNOTIFY" is the user-define notified message

//        case WM_GRAPHNOTIFY:

//        {

//            LONG evCode,evParam1,evParam2;

//

//            //"m_pMedia" is the instance of the CMedia

//            if(m_pMedia->GetEvent(&evCode,&evParam1,&evParam2) == TRUE)

//            {                

//                //Check the event code

//                if(evCode == EC_COMPLETE)

//                {

//                    //Do something

//                }

//            }

//            return 0;

//        } 

//

//    The event code is as follow:

// EC_ACTIVATE                     An audio or video renderer is losing or gaining activation.  

// EC_BUFFERING_DATA               The buffering status is changing.  

// EC_CLOCK_CHANGED                The filter graph has changed from one reference clock to another.  

// EC_COMPLETE                     All data has been rendered.  

// EC_DRM_LEVEL                    Notifies when content protected by digital rights management (DRM) requests some form of analog content protection. 

// EC_END_OF_SEGMENT               Notifies that a segment end has been reached.  

// EC_ERROR_STILLPLAYING           At least one call to Run failed in an active filter graph. 

//                                    The current state of any underlying filter graph or graphs is indeterminate; they might be running, but some are almost certainly not. 

// EC_ERRORABORT                   An error forced the termination of a requested operation.  

// EC_FULLSCREEN_LOST              The video renderer is switching out of full-screen mode.  

// EC_NEED_RESTART                 The current graph must be stopped and restarted.  

// EC_NOTIFY_WINDOW                Pass the window handle around during pin connection.  

// EC_OLE_EVENT                    A filter is passing a text string to the application.  

// EC_OPENING_FILE                 The open file status is changing.  

// EC_PALETTE_CHANGED              The video palette has changed.  

// EC_QUALITY_CHANGE               The playback quality has changed.  

// EC_REPAINT                      A repaint is required.  

// EC_SEGMENT_STARTED              Notifies that a new segment has been started.  

// EC_SHUTTING_DOWN                The filter graph is starting to shut down. 

//                                    DirectShow passes this notification to any plug-in distributors that support the IMediaEventSink interface. 

// EC_STARVATION                   One of the filters (usually a parser or file source filter) is not receiving enough data. 

//                                    By default, the filter graph manager will pause all running filters and then return to normal operation when enough data is available. 

// EC_STREAM_CONTROL_STARTED       The starting reference time from an earlier call to IAMStreamControl::StartAt passed.  

// EC_STREAM_CONTROL_STOPPED       The stopping reference time from an earlier call to IAMStreamControl::StopAt passed.  

// EC_STREAM_ERROR_STILLPLAYING    The stream is still playing, but should not be playing.  

// EC_STREAM_ERROR_STOPPED         The stream has stopped, but should not have stopped.  

// EC_TIME                         The requested reference time occurred.  

// EC_USERABORT                    A user has forced the termination of a requested operation.  

// EC_VIDEO_SIZE_AR_CHANGED        The size or aspect ratio of the native video has changed.  

// EC_VIDEO_SIZE_CHANGED           The size of the native video has changed.  

// EC_WINDOW_DESTROYED             The video renderer's filter is being removed or destroyed.  

//

//

//

//    DirectShow passes the following messages to the window specified by the hWnd parameter, 

//if and when the application generates them: 

// WM_KEYDOWN 

// WM_KEYUP 

// WM_LBUTTONDBLCLK 

// WM_LBUTTONDOWN 

// WM_LBUTTONUP 

// WM_MBUTTONDBLCLK 

// WM_MBUTTONDOWN 

// WM_MBUTTONUP 

// WM_MOUSEACTIVATE 

// WM_MOUSEMOVE 

// WM_RBUTTONDBLCLK 

// WM_RBUTTONDOWN 

// WM_RBUTTONUP 

//-----------------------------------------------------------------------------

BOOL CMedia::SetNotifyWindow(HWND hWnd, UINT wMsg,long lInstanceData)

{



    if(m_pME == NULL)

    {

        return FALSE;

    }


    HRESULT hr;

    hr = m_pME->SetNotifyWindow((OAHWND)hWnd,wMsg,lInstanceData);

    if(FAILED(hr))

    {

        return FALSE;

    }


    if(CheckVisibility() == TRUE && m_pVW != NULL)

    {

        hr = m_pVW->put_MessageDrain((OAHWND)hWnd);

    }





    return SUCCEEDED(hr);

}



//----------------------------------------------------------------------

//Description:

//    This method retrieves the notification event. 

//

//-----------------------------------------------------------------------

BOOL CMedia::GetEvent(LONG *plEvCode, LONG *plParam1, LONG *plParam2)

{

    if(m_pME == NULL)

    {

        return FALSE;

    }


    LONG evCode, evParam1, evParam2;    


    if(SUCCEEDED(m_pME->GetEvent(&evCode, &evParam1, &evParam2, 0)) == TRUE)

    {

        *plEvCode = evCode;

        *plParam1 = evParam1;

        *plParam2 = evParam2;


        // Spin through the events

        m_pME->FreeEventParams(evCode, evParam1, evParam2);        

    }

    else

    {

        return FALSE;

    }



    return TRUE;

}



//----------------------------------------------------------------------

//Description:

//    This method sets a new playback rate. 

//

//Parameters

//    dRate:[in] New rate, where 1 is the normal rate, 2 is twice as fast, and so on. 


//-----------------------------------------------------------------------

BOOL CMedia::SetRate(double dRate)

{

    if(m_pMS == NULL)

    {

        return FALSE;

    }

    return SUCCEEDED(m_pMS->SetRate(dRate));

}



//----------------------------------------------------------------------

//Description:

//    This method retrieves the current rate.

//

//Parameters:

//    pdRate:[out] The rate

//-----------------------------------------------------------------------

BOOL CMedia::GetRate(double *pdRate)

{

    if(m_pMS == NULL)

    {

        return FALSE;

    }


    return SUCCEEDED(m_pMS->GetRate(pdRate));


}


//----------------------------------------------------------------------

//Description:

//    This method retrieves the current position in terms of the total length of the media stream

//

//Parameters:

//    pllPos:[out]Current position.

//-----------------------------------------------------------------------

BOOL CMedia::GetPositionCurrent(LONGLONG *pllPos)

{

    if(m_pMS == NULL)

    {

        return FALSE;

    }


    if(m_dwCapability & AM_SEEKING_CanGetCurrentPos == 0)

    {

        return FALSE;

    }


    return SUCCEEDED(m_pMS->GetCurrentPosition(pllPos));

}


//----------------------------------------------------------------------

//Description:

//    This method sets current positions

//

//Parameters:

//    llPos:[in]Start position if stopped, or position from which to continue if paused. 

//-----------------------------------------------------------------------

BOOL CMedia::SetPositionCurrent(LONGLONG llPos)

{

    if(m_pMS == NULL)

    {

        return FALSE;

    }


    LONGLONG llCur = 0;

    if(GetPositionCurrent(&llCur) == TRUE)

    {

        if((llCur > llPos) && (m_dwCapability & AM_SEEKING_CanSeekBackwards == 0))

        {

            return FALSE;

        }

        else if((llCur < llPos) && (m_dwCapability & AM_SEEKING_CanSeekForwards == 0))

        {            

            return FALSE;            

        }

        else if(llCur == llPos)

        {

            //It's the current positon, needn't set

            return TRUE;

        }

    }

    else if((m_dwCapability & AM_SEEKING_CanSeekBackwards == 0) || (m_dwCapability & AM_SEEKING_CanSeekForwards == 0))

    {

        return FALSE;

    }



    return SUCCEEDED(m_pMS->SetPositions(&llPos,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning));

}



//----------------------------------------------------------------------

//Description:

//    This method get current display mode

//

//----------------------------------------------------------------------

DISPLAYMODE CMedia::GetDisplayMode()

{

    return m_DispMode;

}