#include <windows.h>                       // Needed for Windows.

#include <dshow.h>                         // Needed for DirectShow.
#include "ErG_DirectShow.h"

 

#define CLASSNAME         "EventNotify"   // Window Class Name.

#define WINDOW_WIDTH       640             // Window Width.

#define WINDOW_HEIGHT      480             // Window Height.

#define WM_GRAPHNOTIFY     WM_APP + 1      // Message Handler case.

// Convert from Decibel Level to Logarithmic Scale.

#define DECTOLOG(vol)      (-15 * (100 - vol))

// Convert to scale of (-10,000, 10,000).

#define CONVPAN(pan)        (pan * 100)

 

IBasicAudio   *pBasicAudio   = NULL;

IMediaSeeking *pMediaSeeking = NULL; 

IGraphBuilder *pGraphBuilder    = NULL;    // The Filter Graph Manager.

IMediaControl *pMediaControl    = NULL;    // Control the Movie.

IVideoWindow  *pVideoWindow     = NULL;    // Where the Movie is gonna play.

IMediaEventEx *pMediaEvent      = NULL;    // Handle Movie Events.

HWND          main_hwnd         = NULL;    // The Main Window Handle.

 

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

// Function     :    PlayFile

//

// Input        :    NONE.

//

// Output       :    The Movie Playing.

//

// Purpose      :    Loads and Plays a File.

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

void PlayFile(void)

{

// Create the filter graph manager and render the file.

CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,

IID_IGraphBuilder, (void **)&pGraphBuilder);

 

// Load this File and Build a Filter Graph for it.

pGraphBuilder->RenderFile(L"08-hans_zimmer-parlay.mp3", NULL);

 

// Specify the owner window.
pGraphBuilder->QueryInterface(IID_IBasicAudio, (void **)&pBasicAudio);

pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking); 

// Set the volume.

pBasicAudio->put_Volume(DECTOLOG(50));

// Set the pan.

pBasicAudio->put_Balance(CONVPAN(-100));


pGraphBuilder->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow);

pVideoWindow->put_Owner((OAHWND)main_hwnd);

pVideoWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS);

 

// Make the Movie Take up the Entire Window.

     RECT rect;

     GetClientRect(main_hwnd, &rect);

     pVideoWindow->SetWindowPosition(0, 0, rect.right, rect.bottom);

 

// Set the owner window to receive event notifications.

pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);

pMediaEvent->SetNotifyWindow((OAHWND)main_hwnd, WM_GRAPHNOTIFY, 0);

 

// Run the graph.

pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);

pMediaControl->Run();
}

///////
//Function Restart Stream
//purpose: restarts the audio stream
void RestartStream(void)

{

       // Restart the graph.

       if (pMediaSeeking)

       {

                   LONGLONG llPos = 0;

              pMediaSeeking->SetPositions(&llPos, AM_SEEKING_AbsolutePositioning, &llPos, AM_SEEKING_NoPositioning);

       }

}

 

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

// Function     :    CleanUp

//

// Input        :    None.

//

// Output       :    The Released Resources.

//

// Purpose      :    Shuts down the Movie and all DirectShow related stuff.

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

void CleanUp(void)

{

	if (pMediaSeeking)

	{

		   pMediaSeeking->Release();

		   pMediaSeeking = NULL;

	}

 

	if (pBasicAudio)

	{

		   pBasicAudio->Release();

		   pBasicAudio = NULL;

	}

     if (pMediaControl)                        // Does pMediaControl exist.

     {

           pMediaControl->Stop();               // Stop the graph.

           pMediaControl->Release();            // Release the Movie Controls

           pMediaControl = NULL;                 // Set to NULL for safety.

     }

 

     if (pVideoWindow)                          // Does pVideoWindow exist.

     {

           pVideoWindow->put_Visible(OAFALSE);  // Show no longer.

           pVideoWindow->put_Owner(NULL);       // Have no Owner.

           pVideoWindow->Release();             // Release the Video Window.

           pVideoWindow = NULL;                 // Set to NULL for safety.

     }



 

if (pMediaEvent)                           // Does pMediaEvent exist.

{

     pMediaEvent->Release();              // Release the event manager.

     pMediaEvent = NULL;                  // Set to NULL for safety.

     }

 

     if (pGraphBuilder)                         // Does pGraphBuilder exist.

     {

pGraphBuilder->Release();            // Release the filter graph manager.

pGraphBuilder = NULL;                // Set to NULL for safety.

}

 

     PostQuitMessage(0);                       // Quit the Application Thread.

}

 

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

// Function     :    HandleEvent

//

// Input        :    NONE.

//

// Output       :    The Handled Messages.

//

// Purpose      :    You must have a function to handle any events that the movie might send to

//                   Windows.  The only one you really care about is whether or not the movie is playing.  If

//                   the movie is done playing then you want to shut it down and begin your game or application.

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

void HandleEvent(void)

{

     long evCode, param1, param2;         // Parameters to be set on certain Messages.

     HRESULT result;                      // For Error Tracking.

 

     // Call GetEvent until it returns a failure code, indicating that the queue is empty.

     //while (result = pMediaEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(result))

     //{

     //      result = pMediaEvent->FreeEventParams(evCode, param1, param2);

     //      // If the Sample stops playing or is stopped by the User then call CleanUp.

     //      if ((evCode == EC_COMPLETE) || (evCode == EC_USERABORT))

     //      {

     //           CleanUp();

     //           break;

     //      }

     //}

	 // Call GetEvent until it returns a failure code, indicating that the queue is empty.

       while (result =pMediaEvent->GetEvent(&evCode, &param1, &param2, 0),

				SUCCEEDED(result))

       {

              result = pMediaEvent->FreeEventParams(evCode, param1, param2);

              // If the Sample stops playing or is stopped by the User then call CleanUp.

              if ((evCode == EC_COMPLETE) || (evCode == EC_USERABORT))

              {

                    RestartStream();

                    break;

              }

       }
}

 

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

// Function     :    WindowProc

//

// Input        :    hwnd       -    Handle to the Window.

//                   msg        -    The msg sent to check against.

//                   wparam     -    High order parameter for the message.

//                   lparam     -    Low order parameter for the message.

//

// Return       :    Any unprocessed messages.

//

// Purpose      :    This is the main message handler of the system.

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

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)

{

     // What is the message?

     switch(msg)

     {

           case WM_CREATE:

           {

           return(0);

           }

           break;

 

           // The Case Statement to Handle the Movie Events.

           case WM_GRAPHNOTIFY:

           {

                HandleEvent();

           }

           break;

 

           case WM_KEYDOWN:

           {

                switch(wparam)

                {

                     // Quit the Application.

                     case VK_ESCAPE:

                     {

                           CleanUp();

                     }

                     break;

                }

           }

           break;

 

           case WM_DESTROY:

           {

                CleanUp();

                // Kill the application             

                PostQuitMessage(0);

                return(0);

           }

           break;

 

           default:

           break;

     }

 

     // Process any messages that we didn't take care of

     return (DefWindowProc(hwnd, msg, wparam, lparam));

}

 

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

// Function     :    WinMain

//

// Input        :    hinstance       -    Instance of the application.

//                   hprevinstance   -    No longer used.

//                   lpcmdline       -   

//                   ncmdshow        -

//

// Return       :    High order parameter of the message.

//

// Purpose      :    The main application loop.

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

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,

   LPSTR lpcmdline, int ncmdshow)

{

     WNDCLASS   winclass;       // This will hold the class we create

     MSG        msg;            // Generic message

 

CoInitialize(NULL);        // Initialize COM.

 

     // First fill in the window class structure.

     winclass.style             = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW|

      CS_VREDRAW;

     winclass.lpfnWndProc       = WindowProc;

     winclass.cbClsExtra        = 0;

     winclass.cbWndExtra        = 0;

     winclass.hInstance         = hinstance;

     winclass.hIcon             = LoadIcon(NULL, IDI_APPLICATION);

     winclass.hCursor           = LoadCursor(NULL, IDC_ARROW);

     winclass.hbrBackground     = (HBRUSH)GetStockObject(BLACK_BRUSH);

     winclass.lpszMenuName      = NULL;

     winclass.lpszClassName     = CLASSNAME;

 

     // Register the window class.

     if (!RegisterClass(&winclass))

           return(0);

 

// Create the window.

     if (!(main_hwnd = CreateWindow(CLASSNAME,       // Class Name.

                "Sample Video Window with Events",   // Title of the Window.

WS_POPUP | WS_VISIBLE,               // Window Flags.

0, 0,                                // Window Start Point (x, y).

                WINDOW_WIDTH,                        // Width of Window.

                WINDOW_HEIGHT,                       // Height of Window.

           NULL,                                // Handle to parent.

                NULL,                                // Handle to menu.

                hinstance,                           // Application Instance.

                NULL)))                              // Creation parms.

           return(0);

 

     ShowCursor(false);         // Stop Showing the Cursor.

     PlayFile();                // Play the Movie.

 

     // Enter main event loop

     while(1)

     {

           if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))

           {

                // Test if this is a quit

                if (msg.message == WM_QUIT)

                     break;

                // Translate any accelerator keys

                TranslateMessage(&msg);

                // Send the message to the window proc

                DispatchMessage(&msg);

           }

     }

 

CoUninitialize();         // Uninitialize COM.

 

     // Return to Windows like this

     return(msg.wParam);

}