CMedia更新至v1.4.3

时间:2022-05-10 07:58:23

//========================================================================
//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类型,更符合实际意义


    v1.2.0版本及相关用法见:http://blog.csdn.net/norains/archive/2007/05/14/1609118.aspx

 


    我们来看看具体更新了哪些功能:
   
    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;
}