Announcement

Collapse
No announcement yet.

Media Foundation MediaPlayer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    Yes, the second link is what I am translating now. It uses
    template <classQ> in the Player.cpp.

    Comment


    • #42
      Does this..

      Code:
      '// Return the IMFTopology pointer to the caller.
          *ppTopology = pTopology
          (*ppTopology).AddRef()
      
      translate to this?

      Code:
      '// Return the IMFTopology pointer to the caller.
          ppTopology = VARPTR(pTopology)
          ppTopology.AddRef()
      

      Comment


      • #43
        Surely not. You should learn first how to work with COM with PB. PB does automatic reference counting, whereas the C++ class that you want to translate is using pointers, not objects. The equivalent would be ppTopology = pTopology, but you should learn why.
        Forum: http://www.jose.it-berater.org/smfforum/index.php

        Comment


        • #44
          Famous quote,
          "Regarding low-level COM, only C++ is more powerful, although is much more difficult to use."
          As yet I don't believe I've seen this technique in the Help File ppTopology = pTopology. Does PB COM see through pointers-to-pointers? I know I'm a pain.
          So if I understand you correctly, PB COM does what C++ does not. PB COM tracks references to an object but C++ requires pointers to do the tracking.

          Comment


          • #45
            C++ allows many techniques. Instead of raw pointers, you can use smart pointers, that like PB manage reference counting automatically.
            Forum: http://www.jose.it-berater.org/smfforum/index.php

            Comment


            • #46
              This is what I'm trying to translate...


              [CODE]
              // Static class method to create the CPlayer object.
              HRESULT CPlayer::CreateInstance(
              HWND hVideo,
              // Video window.
              HWND hEvent,
              // Window to receive notifications.
              CPlayer **ppPlayer)
              // Receives a pointer to the CPlayer object.
              {
              if
              (ppPlayer == NULL)
              {
              return
              E_POINTER;
              }

              CPlayer *pPlayer =
              new
              (std::
              nothrow
              ) CPlayer(hVideo, hEvent);
              if
              (pPlayer == NULL)
              {
              return
              E_OUTOFMEMORY;
              }

              HRESULT hr = pPlayer->Initialize();
              if
              (SUCCEEDED(hr))
              {
              *ppPlayer = pPlayer;
              }
              else
              {
              pPlayer->Release();
              }
              return
              hr;
              }




              Code:
              '//  Static class method to create the CPlayer object.
              METHOD CreateInstance( _           'CPlayer method
              BYVAL hVideo AS DWORD _       '// IN HWND Video window.
              , BYVAL hEvent AS DWORD _       '// IN HWND Window to receive notifications.
              , BYVAL ppPlayer AS MyInterface _   '???? '// OUT CPlayer **ppPlayer Receives a pointer to the CPlayer object.
              ) AS LONG
              
                          LOCAL hr AS LONG
                          IF (ISFALSE ISOBJECT(ppPlayer)) THEN
                              FUNCTION = %E_POINTER
                          END IF
              
              CPlayer *pPlayer = NEW (std::nothrow) CPlayer(hVideo, hEvent)
              IF (ISFALSE ISOBJECT(pPlayer)) THEN
                              FUNCTION = %E_OUTOFMEMORY
                          END IF
              
              hr = pPlayer.Initialize()
              IF (SUCCEEDED(hr)) THEN
              *ppPlayer = pPlayer
              ELSE
              pPlayer.Release()
              END IF
                          FUNCTION = hr
              END METHOD

              I'm not sure what to do with NEW (std::nothrow)

              Comment


              • #47
                CPlayer is not a COM object. It is a custom C++ class. If you want to mimic that C++ code you need to implement your CPlayer class.
                Forum: http://www.jose.it-berater.org/smfforum/index.php

                Comment


                • #48
                  This is how I have the CPlayer class designed.


                  Code:
                  CLASS CPLayer $MyClassGuid AS COM
                  
                      INTERFACE IMFAsyncCallbackImpl 'MyInterface $MyIfaceGuid
                  INHERIT IAUTOMATION
                  and the code above in post #46 is a method in the CPlayer class.

                  With this line it looks like the CreateInstance method is trying to create the pPlayer COM object without producing any error messages.


                  Code:
                  CPlayer *pPlayer = NEW (std::nothrow) CPlayer(hVideo, hEvent)
                  There is also a CPlayer method inside the CPlayer class that I assume initializes all global variables and wipes out references to objects.


                  Code:
                  METHOD CPlayer( _             'CPlayer method
                  HWND hVideo _
                  , HWND hEvent) :
                  pMediaSession(NULL),
                  pMediaSource(NULL),
                  pVideoDisplay(NULL),
                  m_hwndVideo(hVideo),
                  m_hwndEvent(hEvent),
                  m_state(%Closed),
                  m_hCloseEvent(NULL),
                  m_nRefCount(1),
                  pCallback(NULL)
                  
                  END METHOD
                  Crazy right!

                  Comment


                  • #49
                    Code:
                    CLASS CPLayer $MyClassGuid AS COM
                    
                        INTERFACE IMFAsyncCallbackImpl 'MyInterface $MyIfaceGuid
                    INHERIT IAUTOMATION
                    Sorry, but it does make any sense. Unfortunately, I don't have time to translate that C++ code to PB.
                    Last edited by José Roca; 6 Jun 2018, 08:01 AM.
                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                    Comment


                    • #50
                      That is ok. I'll keep plugging at it. Thanks

                      Comment


                      • #51
                        Here is the example I cobbled together to show my problem creating a Media Source. I've also tried the asynchronous method but it didn't work either. Please help


                        Code:
                        'This is a translation of this site:
                        'https://chromium.googlesource.com/webm/webmdshow/+/refs/heads/master/mediafoundation/webmmftests/mfplay/player.cc
                        
                        
                        '/////////////////////////////////////////////////////////////////////////////////
                        '// by: Jim Fritts on 13 JUNE 2018
                        '// From OLD MSDN Media Foundation Media Player example.
                        '//
                        '// Note: This example will compile.
                        '//       It is just for your info.
                        '//       Change sURL to match an audio path in your own music library.
                        '//       See here ////////  NEVER GETS HERE  //////// for problem area.
                        '//       Problem is the Source is never created.
                        '//
                        '/////////////////////////////////////////////////////////////////////////////////
                        
                        'TRUE = -1
                        'FALSE = 0
                        
                        '/////////////////////////////////////////////////////////////////
                        '/////////////////////// CPlayer Class EX ////////////////////////
                        '/////////////////////////////////////////////////////////////////
                        'Example class for Player
                        'CLASS MyClass
                        ' INSTANCE MyVar AS LONG
                        '
                        ' CLASS METHOD CREATE()        'A CLASS METHOD IS PRIVATE
                        '   ' Do initialization
                        ' END METHOD
                        '
                        ' CLASS METHOD DESTROY()       'A CLASS METHOD IS PRIVATE
                        '   ' Do cleanup
                        ' END METHOD
                        '
                        ' INTERFACE MyInterface
                        '   INHERIT IUNKNOWN
                        '   METHOD MyMethod1 <101> ()  '<> DISPATCH ID
                        '     ' Do things
                        '   END METHOD
                        '
                        '   METHOD MyMethod2 <102> () AS LONG      '*******************
                        '     ' Do things
                        '     METHOD = RETURN VALUE  '******************
                        '   END METHOD
                        ' END INTERFACE
                        '
                        'END CLASS
                        '/////////////////////////////////////////////////////////////////
                        
                        'COM RETURN VALUES
                        '%E_ACCESSDENIED 0x80070005 Access denied.
                        '%E_FAIL         0x80004005 Unspecified error.
                        '%E_INVALIDARG   0x80070057 Invalid parameter value.
                        '%E_OUTOFMEMORY  0x8007000E Out of memory.
                        '%E_POINTER      0x80004003 NULL was passed incorrectly for a pointer value.
                        '%E_UNEXPECTED   0x8000FFFF Unexpected condition.
                        '%S_OK           0x0        Success.
                        '%S_FALSE        0x1        Success.
                        
                        '// Application should not call MFStartup / MFShutdown from workqueue threads
                        
                        '/////////////////////////////////////////////////////////////////
                        
                        #COMPILE EXE
                        #DIM ALL
                        #INCLUDE ONCE "windows.inc"
                        #INCLUDE ONCE "mfapi.inc"
                        #INCLUDE ONCE "mfidl.inc"
                        #INCLUDE ONCE "evr.inc"  'needed for video display control
                        #INCLUDE ONCE "Mferror.inc"
                        #INCLUDE ONCE "ObjBase.inc"
                        
                        'These must be the globals
                        '    pMediaSession(NULL),
                        '    pMediaSource(NULL),
                        
                        '    m_hwndVideo(hVideo),
                        '    m_hwndEvent(hEvent),
                        '    m_state(%Closed),
                        '    m_hCloseEvent(NULL),
                        
                        '    pVideoDisplay(NULL),
                        '    m_nRefCount(1),
                        '    pCallback(NULL)
                        
                        GLOBAL m_hwndAudio        AS LONG
                        GLOBAL m_state            AS LONG
                        GLOBAL m_hCloseEvent      AS LONG
                        GLOBAL m_hwndVideo        AS LONG
                        GLOBAL m_hwndEvent        AS LONG       '// App window to receive events.
                        GLOBAL m_nRefCount        AS LONG
                        GLOBAL m_PresentationTimeOffset AS LONG
                        
                        GLOBAL pMediaSession      AS IMFMediaSession
                        GLOBAL pMediaSource       AS IMFMediaSource
                        GLOBAL pPlayer            AS IMFAsyncCallbackImpl 'MyInterface    'IMFAsyncCallbackImpl
                        GLOBAL pVideoDisplay      AS IMFVideoDisplayControl
                        GLOBAL pCallback          AS IMFAsyncCallback 'IMFAsyncCallbackImpl   ' Object reference to the IMFAsyncCallback Interface
                        GLOBAL pConfiguration     AS IMFAttributes
                        
                        GLOBAL giHasStarted       AS LONG   'tracks media foundation start and stop
                        
                        GLOBAL MFStatus           AS STRING
                        GLOBAL sURL               AS ASCIIZ * 255
                        GLOBAL TrackTitle         AS STRING
                        GLOBAL SessionStatus      AS STRING
                        GLOBAL SSMessages         AS STRING
                        GLOBAL SourceStatus       AS STRING
                        GLOBAL LastButton         AS INTEGER
                        
                        GLOBAL wsURL              AS WSTRINGZ * 255
                        'GLOBAL pwsURL             AS WSTRINGZ POINTER
                        
                        $MyClassGuid = GUID$("{00000099-0000-0000-0000-000000000008}")
                        $MyIfaceGuid = GUID$("{00000099-0000-0000-0000-000000000009}")
                        
                        GLOBAL hDlg    AS DWORD
                        GLOBAL DoPlay  AS DWORD
                        
                        %WM_APP_PLAYER_EVENT = 1010
                        
                        %LabelMFStatus      = 101
                        %LabelTrack         = 102
                        %TextboxText        = 103
                        
                        %ButtonPlay         = 401
                        %ButtonPause        = 402
                        %ButtonStop         = 403
                        %ButtonExit         = 404
                        
                        %ButtonMFStartUp    = 405
                        %ButtonMFShutDown   = 406
                        
                        %ButtonOpenSession  = 407
                        %ButtonCloseSession = 408
                        
                        %ButtonOpenSource   = 409
                        %ButtonCloseSource  = 410
                        
                        '%LabelFormat    = 102
                        '%LabelVolume    = 103
                        '%LabelText      = 105
                        '%ListboxVoice   = 201
                        
                        '%FrameVolume    = 601
                        '%FrameSpeed     = 602
                        '%ComboFormat    = 701
                        
                        'ENUM MF_OBJECT_TYPE
                           %MF_OBJECT_MEDIASOURCE = 0
                           %MF_OBJECT_BYTESTREAM  = 1
                           %MF_OBJECT_INVALID     = 2
                        'END ENUM
                        
                        TYPE MF_OBJECT_TYPE
                          ABC AS INTEGER
                        END TYPE
                        
                        
                        ENUM PlayerState SINGULAR   'm_state values
                            Closed = 0     '// No session.
                            Ready          '// Session was created, ready to open a file.
                            OpenPending    '// Session is opening a file.
                            Started        '// Session is playing a file.
                            Paused         '// Session is paused.
                            Stopped        '// Session is stopped (ready to play).
                            Closing        '// Application has closed the session, but is waiting for MESessionClosed.
                        END ENUM
                        
                        
                        FUNCTION SafeRelease(BYREF ppT AS IUNKNOWN) AS LONG
                            IF ISOBJECT(ppT) THEN
                                ppT.Release
                                ppT = NOTHING
                            END IF
                        END FUNCTION
                        
                        DECLARE FUNCTION PathFileExists LIB "SHLWAPI.DLL" ALIAS "PathFileExistsA"(BYREF pszPath AS ASCIIZ) AS LONG
                        
                        DECLARE FUNCTION SetEvent IMPORT "KERNEL32.DLL" ALIAS "SetEvent" ( _
                           BYVAL hEvent AS DWORD _                              ' __in HANDLE hEvent
                         ) AS LONG                                              ' BOOL
                        
                        DECLARE FUNCTION MFStartup IMPORT "MFPLAT.DLL" ALIAS "MFStartup" ( _
                           BYVAL Version AS DWORD _                             ' __in ULONG Version
                         , BYVAL dwFlags AS DWORD _                             ' __in DWORD dwFlags
                         ) AS LONG                                              ' HRESULT
                        
                        '______________________________________________________________________________
                        
                        CALLBACK FUNCTION DlgProc
                         STATIC hControlFocus AS DWORD
                        
                         SELECT CASE CBMSG
                        
                           CASE %WM_INITDIALOG
                             SetFocus GetDlgItem(hDlg, %ButtonExit)
                             LastButton = %ButtonExit
                        
                           CASE %WM_COMMAND
                             SELECT CASE LOWRD(CBWPARAM)
                        
                               CASE %WM_APP_PLAYER_EVENT
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     ? "A player event was sent"
                                 END IF
                        
                               CASE %ButtonPlay
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonPlay)
                        
                                     IF SessionStatus = "Media Session is open." AND _
                                        TrackTitle <> "----- Track Not Found -----" AND _
                                        giHasStarted = 1 THEN
                                         IF (DoPlay = 0 OR DoPlay = 2) THEN
                                             DoPlay = 1
                                             'StartPlaying
                                             CONTROL DISABLE hDlg, %ButtonPlay
                        
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL ENABLE hDlg, %ButtonPause
                        
                                             CONTROL DISABLE hDlg, %ButtonStop
                                             CONTROL ENABLE hDlg, %ButtonStop
                                             SetButtonFocus(hDlg, %ButtonPlay, %ButtonStop)
                                             LastButton = %ButtonStop
                                         ELSE
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL DISABLE hDlg, %ButtonStop
                        
                                         END IF
                                     ELSE
                                         CONTROL DISABLE hDlg, %ButtonPlay
                                         CONTROL DISABLE hDlg, %ButtonPause
                                         CONTROL DISABLE hDlg, %ButtonStop
                        
                                     END IF
                                 END IF
                        
                               CASE %ButtonPause
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonPause)
                        
                                     IF SessionStatus = "Media Session is open." AND _
                                        TrackTitle <> "----- Track Not Found -----" AND _
                                        giHasStarted = 1 THEN
                                         IF DoPlay = 1 THEN
                                             DoPlay = 2
                                             'PausePlaying
                                             CONTROL DISABLE hDlg, %ButtonPause
                        
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL ENABLE hDlg, %ButtonPlay
                        
                                             CONTROL DISABLE hDlg, %ButtonStop
                                             CONTROL ENABLE hDlg, %ButtonStop
                                             SetButtonFocus(hDlg, %ButtonPause, %ButtonPlay)
                                             LastButton = %ButtonPlay
                                         END IF
                                     ELSE
                                         CONTROL DISABLE hDlg, %ButtonPlay
                                         CONTROL DISABLE hDlg, %ButtonPause
                                         CONTROL DISABLE hDlg, %ButtonStop
                        
                                     END IF
                                 END IF
                        
                               CASE %ButtonStop
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonStop)
                        
                                     IF SessionStatus = "Media Session is open." AND _
                                        TrackTitle <> "----- Track Not Found -----" AND _
                                        giHasStarted = 1 THEN
                                         DoPlay = 0
                                         CONTROL DISABLE hDlg, %ButtonPlay
                                         CONTROL DISABLE hDlg, %ButtonPause
                                         CONTROL DISABLE hDlg, %ButtonStop
                                         IF SessionStatus = "Media Session is open." THEN
                                             CONTROL ENABLE hDlg, %ButtonPlay
                                             SetButtonFocus(hDlg, %ButtonStop, %ButtonPlay)
                                             LastButton = %ButtonPlay
                                         END IF
                                     ELSE
                                         CONTROL DISABLE hDlg, %ButtonPlay
                                         CONTROL DISABLE hDlg, %ButtonPause
                                         CONTROL DISABLE hDlg, %ButtonStop
                        
                                     END IF
                                 END IF
                        
                               CASE %ButtonExit
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonExit)
                        
                                     DIALOG END hDlg
                                 END IF
                        
                               CASE %ButtonMFStartUp
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonMFStartUp)
                        
                                     IF giHasStarted = 0 THEN
                                         CALL pPlayer.Initialize()
                                         IF giHasStarted = 1 THEN
                                             CONTROL DISABLE hDlg, %ButtonMFStartUp
                                             CONTROL DISABLE hDlg, %ButtonMFShutDown
                                             CONTROL ENABLE hDlg, %ButtonMFShutDown
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL DISABLE hDlg, %ButtonStop
                        
                                             CONTROL DISABLE hDlg, %ButtonOpenSession
                                             CONTROL DISABLE hDlg, %ButtonCloseSession
                                             IF TrackTitle <> "----- Track Not Found -----" AND _
                                                SessionStatus = "Media Session is closed." THEN
                                                 CONTROL ENABLE hDlg, %ButtonOpenSession
                                                 SetButtonFocus(hDlg, %ButtonMFStartUp, %ButtonOpenSession)
                                                 LastButton = %ButtonOpenSession
                                             END IF
                                         END IF
                                     END IF
                                 END IF
                        
                               CASE %ButtonMFShutDown
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonMFShutDown)
                        
                                     IF giHasStarted = 1 THEN
                                         CALL pPlayer.Shutdown()
                                         IF giHasStarted = 0 THEN
                                             CONTROL DISABLE hDlg, %ButtonMFShutDown
                                             CONTROL DISABLE hDlg, %ButtonMFStartUp
                                             CONTROL ENABLE hDlg, %ButtonMFStartUp
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL DISABLE hDlg, %ButtonStop
                                             CONTROL DISABLE hDlg, %ButtonOpenSession
                                             CONTROL DISABLE hDlg, %ButtonCloseSession
                                             CONTROL DISABLE hDlg, %ButtonOpenSource
                                             CONTROL DISABLE hDlg, %ButtonCloseSource
                                             SessionStatus = "Media Session is closed."
                                             SetButtonFocus(hDlg, %ButtonMFShutDown, %ButtonMFStartUp)
                                             LastButton = %ButtonMFStartUp
                                         END IF
                                     END IF
                                 END IF
                        
                               CASE %ButtonOpenSession
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonOpenSession)
                        
                                     IF giHasStarted = 1 THEN
                                         IF SessionStatus = "Media Session is closed." THEN
                                             'open session
                                             CALL pPlayer.OpenSession()
                                             'SessionStatus = "Media Session is open."
                                             CONTROL DISABLE hDlg, %ButtonOpenSession
                                             CONTROL DISABLE hDlg, %ButtonCloseSession
                                             CONTROL ENABLE hDlg, %ButtonCloseSession
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL DISABLE hDlg, %ButtonStop
                                             DoPlay = 0
                        
                                             IF SessionStatus = "Media Session is open." AND _
                                                TrackTitle <> "----- Track Not Found -----" AND _
                                                SourceStatus = "No Source created." THEN
                                                 CONTROL DISABLE hDlg, %ButtonOpenSource
                                                 CONTROL ENABLE hDlg, %ButtonOpenSource
                                                 SetButtonFocus(hDlg, %ButtonOpenSession, %ButtonOpenSource)
                                                 LastButton = %ButtonOpenSource
                                             END IF
                                         END IF
                        
                                     END IF
                                 END IF
                        
                               CASE %ButtonCloseSession
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonCloseSession)
                        
                                     IF giHasStarted = 1 THEN
                                         IF SessionStatus = "Media Session is open." THEN
                                             'close session
                                             CALL pPlayer.CloseSession()
                                             'SessionStatus = "Media Session is closed."
                                             CONTROL DISABLE hDlg, %ButtonOpenSession
                                             CONTROL ENABLE hDlg, %ButtonOpenSession
                                             CONTROL DISABLE hDlg, %ButtonCloseSession
                                             CONTROL DISABLE hDlg, %ButtonPlay
                                             CONTROL DISABLE hDlg, %ButtonPause
                                             CONTROL DISABLE hDlg, %ButtonStop
                                             CONTROL DISABLE hDlg, %ButtonOpenSource
                                             SetButtonFocus(hDlg, %ButtonCloseSession, %ButtonOpenSession)
                                             LastButton = %ButtonOpenSession
                                         END IF
                        
                                     END IF
                                 END IF
                        
                               CASE %ButtonOpenSource
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonOpenSource)
                        
                                     IF giHasStarted = 1 AND SessionStatus = "Media Session is open." THEN
                                         IF SourceStatus = "No Source created." THEN
                        
                                             CALL pPlayer.OpenMyMediaSource(wsURL, pMediaSource)  'pwsURL
                        
                                             CONTROL DISABLE hDlg, %ButtonOpenSource
                                             CONTROL DISABLE hDlg, %ButtonCloseSource
                                             CONTROL ENABLE hDlg, %ButtonCloseSource
                                             SetButtonFocus(hDlg, %ButtonOpenSource, %ButtonCloseSource)
                                             LastButton = %ButtonCloseSource
                                         END IF
                                     END IF
                                 END IF
                        
                               CASE %ButtonCloseSource
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                     SetButtonFocus(hDlg, LastButton, %ButtonCloseSource)
                        
                                     IF giHasStarted = 1 AND SessionStatus = "Media Session is open." THEN
                                         IF SourceStatus = "The Media Source was created." THEN
                        
                                             CALL pPlayer.CloseMediaSource()
                        
                                             CONTROL DISABLE hDlg, %ButtonOpenSource
                                             CONTROL DISABLE hDlg, %ButtonCloseSource
                                             CONTROL ENABLE hDlg, %ButtonOpenSource
                                             SetButtonFocus(hDlg, %ButtonCloseSource, %ButtonOpenSource)
                                             LastButton = %ButtonOpenSource
                                         END IF
                                     END IF
                                 END IF
                        
                        
                             END SELECT
                        
                           CASE %WM_NCACTIVATE
                             IF CBWPARAM THEN
                               IF hControlFocus THEN
                                 SetFocus(hControlFocus)
                                 hControlFocus = 0
                               END IF
                             ELSE
                               hControlFocus = GetFocus()
                             END IF
                        
                          END SELECT
                        
                        END FUNCTION
                        '______________________________________________________________________________
                        
                        FUNCTION PBMAIN () AS LONG
                        
                          DIALOG FONT "Segoe UI", 9
                          DIALOG NEW %HWND_DESKTOP, ExeName2(6), , , 312, 336, _
                          %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hDlg
                        
                          SetClassLong hDlg, %GCL_HICON, ExtractIcon(GetModuleHandle(""), "%SystemRoot%\system32\wpdshext.dll", 6)
                        
                          MFStatus = "Media Foundation is closed."
                          SessionStatus = "Media Session is closed."
                          SourceStatus = "No Source created."
                        
                          'local CPlayer as pPlayer iunknown
                          pPlayer     = CLASS "CPlayer"
                          pCallback   = CLASS "CMFAsyncCallback"           ' Create an instance of the CPlayer object
                        
                          '//////// Change this info to match your music library /////////
                          sURL = "C:\Users\Public\Music\Aaron Tippin\Greatest Hits...and Then Some\01 Cold Gray Kentucky Morning.wma"
                          'sURL = "C:\Users\Public\Music\Billy Idol\The Very Best of Billy Idol\05 Eyes Without a Face.mp3"
                          'sURL = "C:\Users\Public\Music\Afterlife & Cathy Battistessa\Speck of Gold\01 Speck of Gold.m4a"
                        
                          TrackTitle = "----- Track Not Found -----"
                        
                          IF FileExists(sURL) THEN
                              TrackTitle = FileNam(sURL)
                        
                              wsURL = sURL + $NUL
                              '? "]" + wsURL + "["
                              'pwsURL = VARPTR(wsURL)
                              'OpenURL(BYVAL pwsURL)
                          END IF
                        
                          CONTROL ADD LABEL, hDlg, %LabelMFStatus, "Audio Track Name:", 5, 5, 120, 10
                          CONTROL ADD LABEL, hDlg, %LabelTrack, TrackTitle, 5, 15, 120, 10
                        
                          CONTROL ADD TEXTBOX, hDlg, %TextboxText, SSMessages, _
                          5, 35, 220, 200, _
                          %WS_CHILD OR %WS_VISIBLE OR %ES_AUTOHSCROLL OR %WS_VSCROLL OR _
                          %ES_NOHIDESEL OR %ES_READONLY OR %ES_MULTILINE OR %WS_BORDER
                        
                        
                          CONTROL ADD BUTTON, hDlg, %ButtonMFStartUp, "MF StartUp", 236, 10, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          CONTROL ADD BUTTON, hDlg, %ButtonMFShutDown, "MF ShutDown", 236, 30, 72, 15, %WS_TABSTOP
                        
                          IF TrackTitle = "----- Track Not Found -----" OR _
                             MFStatus = "Media Foundation is closed." THEN
                              CONTROL ADD BUTTON, hDlg, %ButtonOpenSession, "Open Session", 236, 50, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                              CONTROL ADD BUTTON, hDlg, %ButtonCloseSession, "Close Session", 236, 70, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          ELSE
                              CONTROL ADD BUTTON, hDlg, %ButtonOpenSession, "Open Session", 236, 50, 72, 15, %WS_TABSTOP
                              CONTROL ADD BUTTON, hDlg, %ButtonCloseSession, "Close Session", 236, 70, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          END IF
                        
                          IF TrackTitle = "----- Track Not Found -----" OR _
                             MFStatus = "Media Foundation is closed." OR _
                             SessionStatus = "Media Session is closed." THEN
                              CONTROL ADD BUTTON, hDlg, %ButtonOpenSource, "Open Source", 236, 90, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                              CONTROL ADD BUTTON, hDlg, %ButtonCloseSource, "Close Source", 236, 110, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          ELSE
                              CONTROL ADD BUTTON, hDlg, %ButtonOpenSource, "Open Source", 236, 90, 72, 15, %WS_TABSTOP
                              CONTROL ADD BUTTON, hDlg, %ButtonCloseSource, "Close Source", 236, 110, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          END IF
                        
                        
                        
                          IF SessionStatus = "Media Session is open." AND _
                             DoPlay = 0 AND _
                             TrackTitle <> "----- Track Not Found -----" AND _
                             giHasStarted = 1 THEN
                              CONTROL ADD BUTTON, hDlg, %ButtonPlay, "Play", 5, 318, 72, 15, %WS_TABSTOP
                          ELSE
                              CONTROL ADD BUTTON, hDlg, %ButtonPlay, "Play", 5, 318, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                          END IF
                        
                          CONTROL ADD BUTTON, hDlg, %ButtonPause, "Pause", 82, 318, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                        
                          CONTROL ADD BUTTON, hDlg, %ButtonStop, "Stop", 159, 318, 72, 15, %WS_DISABLED OR %WS_TABSTOP
                        
                          CONTROL ADD BUTTON, hDlg, %ButtonExit, "Exit", 236, 318, 72, 15, %WS_TABSTOP
                        
                          DIALOG SHOW MODAL hDlg CALL DlgProc
                        
                        END FUNCTION
                        
                        '///////////////////////////////////////////////////////////////////////////
                        '// FUNCTIONS SECTION
                        '///////////////////////////////////////////////////////////////////////////
                        
                        '______________________________________________________________________________
                        
                        FUNCTION ExeName2(Action AS LONG) AS STRING 'Return the ExeName of this APP or ExeName of calling app if DLL
                         LOCAL zFileName   AS ASCIIZ * %MAX_PATH
                         LOCAL PathFileLen AS LONG
                         LOCAL FileExtLen  AS LONG
                         LOCAL DotPos      AS LONG
                         LOCAL SlashPos    AS LONG
                        
                         PathFileLen = GetModuleFileName(0, zFileName, %MAX_PATH)
                         SlashPos = INSTR(-1, zFileName, "\")
                         DotPos = INSTR(-1, zFileName, ".")
                         IF DotPos < SlashPos THEN DotPos = 0
                         FileExtLen = PathFileLen - SlashPos
                        
                         SELECT CASE Action
                        
                           CASE 1 'C: - Drive
                             IF ASC(zFileName, 2) = 58 THEN 'X: 58
                               FUNCTION = LEFT$(zFileName, 2)
                             END IF
                        
                           CASE 2 'C:\Subdir\ - Drive and Path (Including last backslash)
                             FUNCTION = LEFT$(zFileName, SlashPos)
                        
                           CASE 3 '\Subdir\ - Path (Including first and last backslash)
                             FUNCTION = MID$(zFileName, 3, SlashPos - 2)
                        
                           CASE 4 'C:\Subdir\File - Drive, Path and Filename (No Extention, Dot excluded)
                             IF DotPos THEN
                               FUNCTION = LEFT$(zFileName, DotPos - 1)
                             ELSE
                               FUNCTION = LEFT$(zFileName, PathFileLen)
                             END IF
                        
                           CASE 5 'C:\Subdir\File.Exe - Path, Filename and Extention
                             FUNCTION = LEFT$(zFileName, PathFileLen)
                        
                           CASE 6 'File - Filename (No Extention)
                             IF DotPos THEN
                               FUNCTION = MID$(zFileName, SlashPos + 1, FileExtLen - (PathFileLen - DotPos) - 1)
                             ELSE
                               FUNCTION = MID$(zFileName, SlashPos + 1, FileExtLen)
                             END IF
                        
                           CASE 7 'File.Exe - Filename and Extention
                             FUNCTION = MID$(zFileName, SlashPos + 1, FileExtLen)
                        
                           CASE 8 '.Exe - Extention (Including Dot)
                             FUNCTION = MID$(zFileName, DotPos)
                        
                         END SELECT
                        
                        END FUNCTION
                        '______________________________________________________________________________
                        
                        
                        DECLARE FUNCTION MFCreateSourceResolver IMPORT "mf.dll" ALIAS "MFCreateSourceResolver" ( _
                           BYREF ppISourceResolver AS IMFSourceResolver _       ' __out IMFSourceResolver **ppISourceResolver
                         ) AS LONG                                              ' HRESULT
                        
                        DECLARE FUNCTION CoInitializeEx IMPORT "OLE32.DLL" ALIAS "CoInitializeEx" ( _
                           BYVAL pvReserved AS DWORD _                          ' __in void * pvReserved
                         , BYVAL dwCoInit AS DWORD _                            ' __in DWORD dwCoInit
                         ) AS LONG                                              ' HRESULT
                        
                        DECLARE FUNCTION CoInitialize IMPORT "OLE32.DLL" ALIAS "CoInitialize" ( _
                           OPTIONAL BYVAL pvReserved AS DWORD _                 ' __in LPVOID pvReserved
                         ) AS LONG                                              ' HRESULT
                        
                        DECLARE SUB CoUninitialize IMPORT "OLE32.DLL" ALIAS "CoUninitialize" ()   ' void
                        
                        
                        DECLARE FUNCTION MFCreateMediaEvent IMPORT "MFPLAT.DLL" ALIAS "MFCreateMediaEvent" ( _
                           BYVAL met AS DWORD _                                 ' __in  MediaEventType met
                         , BYREF guidExtendedType AS GUID _                     ' __in  REFGUID guidExtendedType
                         , BYVAL hrStatus AS LONG _                             ' __in  HRESULT hrStatus
                         , BYREF pvValue AS ANY _                               ' __in  const PROPVARIANT* pvValue
                         , BYREF ppEvent AS IMFMediaEvent _                     ' __out IMFMediaEvent ** ppEvent
                         ) AS LONG                                              ' HRESULT
                        
                        
                        DECLARE FUNCTION CreateEventW IMPORT "KERNEL32.DLL" ALIAS "CreateEventW" ( _
                           BYREF lpEventAttributes AS SECURITY_ATTRIBUTES _     ' __in LPSECURITY_ATTRIBUTES lpEventAttributes
                         , BYVAL bManualReset AS LONG _                         ' __in BOOL bManualReset
                         , BYVAL bInitialState AS LONG _                        ' __in BOOL bInitialState
                         , BYREF lpName AS WSTRINGZ _                           ' __in LPCWSTR lpName
                         ) AS DWORD                                             ' HANDLE
                        
                        
                        
                        
                        
                        'CLASS MyClass $MyClassGuid AS COM
                        '    INTERFACE MyInterface $MyIfaceGuid
                        '        INHERIT IAutomation
                        '        METHOD Method1(parm AS LONG)
                        '            CALL abc(parm)
                        '        END METHOD
                        '    END INTERFACE
                        'END CLASS
                        
                        
                        '///////////////////////////////////////////////////////////////////////////
                        '// CLASS SECTION
                        '///////////////////////////////////////////////////////////////////////////
                        
                        CLASS CPLayer $MyClassGuid AS COM
                        
                            CLASS METHOD CREATE()  'Initialize() AS LONG                         'CPlayer method
                                IF giHasStarted = 0 THEN
                                    LOCAL pvReserved AS DWORD
                                    LOCAL lpEventAttributes AS SECURITY_ATTRIBUTES
                                    LOCAL bManualReset AS LONG
                                    LOCAL bInitialState AS LONG
                                    LOCAL lpName AS WSTRINGZ * 255
                        
                                    ' Do initialization
                                    'MFStartup
                                    '   BYVAL Version AS DWORD _                             ' __in ULONG Version
                                    ' , BYVAL dwFlags AS DWORD _                             ' __in DWORD dwFlags
                        
                                    '// Start up Media Foundation platform.
                                    LOCAL hr AS LONG
                        
                                    '// initialize COM
                                    hr = CoInitializeEx(pvReserved, %COINIT_APARTMENTTHREADED)
                                    IF FAILED(hr) THEN
                                        MFStatus = "Media Foundation was closed."
                                        CONTROL SET TEXT hDlg, %TextboxText, "The COM libraries were not enabled."
                                        GOTO done
                                    END IF
                        
                                    hr = MFStartup(%MF_API_VERSION, 0)     ' %MF_VERSION ' %MF_API_VERSION, 0 = full MF
                                    IF (SUCCEEDED(hr)) THEN
                                        '// create an event that will be fired when the asynchronous IMFMediaSession::Close()
                                        '// operation is complete
                                        m_hCloseEvent = CreateEventW(lpEventAttributes, %FALSE, %FALSE, lpName)
                                        IF m_hCloseEvent = %NULL THEN
                                            'BREAK_ON_NULL(m_hCloseEvent, %E_UNEXPECTED)
                                            m_hCloseEvent = %E_UNEXPECTED
                                            ? "here ?"
                                            GOTO done
                                        END IF
                        
                                        'm_hCloseEvent = CreateEventW(%NULL, %FALSE, %FALSE, %NULL)
                                        'IF (m_hCloseEvent = %NULL) THEN
                                        '    hr = HRESULT_FROM_WIN32(GetLastError())
                                        'END IF
                                        giHasStarted = 1
                                        MFStatus = "Media Foundation was opened."
                                        SSMessages = MFStatus + $CRLF
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                    END IF
                                END IF
                            done:
                            END METHOD
                        
                            '//  Release all resources held by this object.
                            CLASS METHOD DESTROY() 'AS LONG 'Shutdown() AS LONG            'cplayer method
                                IF giHasStarted = 1 THEN
                                    ' Do Cleanup
                        
                                    LOCAL hr AS LONG
                        
                                    '// Close the session
                                    IF SessionStatus = "Media Session is open." THEN
                                        hr = pPlayer.CloseSession()
                                    END IF
                        
                                    '// Shutdown the Media Foundation platform
                                    MFShutdown()
                        
                                    IF (m_hCloseEvent) THEN
                                        CloseHandle(m_hCloseEvent)
                                    END IF
                        
                                    giHasStarted = 0
                                    MFStatus = "Media Foundation was closed."
                                    SSMessages = MFStatus + $CRLF
                                    CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                        
                                    CALL CoUninitialize  'removes COM libraries
                                END IF
                            END METHOD
                        
                        
                        
                            INTERFACE  IMFAsyncCallbackImpl 'MyInterface $MyIfaceGuid  'IMFAsyncCallbackImpl
                                INHERIT IUNKNOWN 'IDISPATCH
                        
                        
                                METHOD Initialize() AS LONG                         'CPlayer method
                                    ME.Create()
                                END METHOD
                        
                                METHOD Shutdown() AS LONG                           'CPlayer method
                                    '// If FALSE, the app did not call Shutdown().
                        
                                    '// When CPlayer calls IMediaEventGenerator::BeginGetEvent on the
                                    '// media session, it causes the media session to hold a reference
                                    '// count on the CPlayer.
                        
                                    '// This creates a circular reference count between CPlayer and the
                                    '// media session. Calling Shutdown breaks the circular reference
                                    '// count.
                        
                                    '// If CreateInstance fails, the application will not call
                                    '// Shutdown. To handle that case, call Shutdown in the destructor.
                        
                                    ME.Destroy()
                                END METHOD
                        
                                '//  Close the media source.
                                METHOD CloseMediaSource() AS LONG
                                    SafeRelease(pMediaSource)
                                    SourceStatus = "No Source created."
                                    SSMessages = SourceStatus + $CRLF + SSMessages
                                    CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                        
                                END METHOD
                        
                                '////////////////////////////////////////////////
                                ' ORIGINAL VARIABLES
                                '  PCWSTR pszURL _
                                ', IMFMediaSource **ppSource _
                                '////////////////////////////////////////////////
                                '//  Create a media source from a URL.
                                METHOD OpenMyMediaSource( _
                                     BYVAL pszUrl AS WSTRINGZ * 255 _                   ' __in LPCWSTR pszUrl
                                   , BYREF ppMediaSource AS IMFMediaSource _            ' __out IMFMediaSource **ppMediaSource
                                   ) AS LONG
                        
                                    LOCAL hr               AS LONG
                        
                                    LOCAL pObjectType      AS LONG  'MF_OBJECT_TYPE
                                    LOCAL pSourceResolver  AS IMFSourceResolver
                                    LOCAL pProps           AS IPropertyStore
                                    LOCAL pSource          AS IUNKNOWN
                        
                                    'MF_OBJECT_TYPE ObjectType = %MF_OBJECT_INVALID
                                    'IMFSourceResolver* pSourceResolver = NOTHING
                                    'IUNKNOWN* pSource = NOTHING
                        
                                    '? pszUrl
                        
                                    'I have tried BeginCreateObjectFromURL to no avail
                        
                                    pObjectType = %MF_OBJECT_INVALID
                        
                                    '// Create the source resolver.
                                    hr = MFCreateSourceResolver(pSourceResolver)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                                    ? "The Source Resolver was created."
                        
                                    '// Use the source resolver to create the media source.
                        
                                    '// Note: For simplicity this sample uses the synchronous method to create
                                    '// the media source. However, creating a media source can take a noticeable
                                    '// amount of time, especially for a network source. For a more responsive
                                    '// UI, use the asynchronous BeginCreateObjectFromURL method.
                        
                                    ' ' =====================================================================================
                                    ' METHOD CreateObjectFromURL ( _                       ' VTable offset = 12
                                    '   BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                                    ' , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                                    ' , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                                    ' , BYVAL pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                                    ' , BYREF ppObject AS IUnknown _                       ' __out IUnknown **ppObject
                                    ' ) AS LONG                                            ' HRESULT
                                    ' ' =====================================================================================
                        
                                    hr = pSourceResolver.CreateObjectFromURL( _
                                         pszUrl _                     '// URL of the source.  Null-terminated string that contains the URL to resolve
                                       , %MF_RESOLUTION_MEDIASOURCE _ '// Create a source object.
                                       , pProps _                     '// Optional property store.
                                       , pObjectType _                '// Receives the created object type.
                                       , pSource _                    '// Receives a pointer to the media source.
                                       )
                        
                                    '///////////////////////////////////
                                    '////////  NEVER GETS HERE  ////////
                                    '///////////////////////////////////
                        
                                    ? "The media source may have been created."
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Get the IMFMediaSource interface from the media source.
                                    'hr = pSource.QueryInterface(IID_PPV_ARGS(ppMediaSource))
                                    IF ISOBJECT(pSource) THEN
                                        ppMediaSource = pSource
                                    END IF
                                    SourceStatus = "The Media Source was created."
                                    SSMessages = SourceStatus + $CRLF + SSMessages
                                    CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                        
                                done:
                                    SafeRelease(pProps)
                                    SafeRelease(pSourceResolver)
                                    SafeRelease(pSource)
                        
                                    METHOD = hr
                                END METHOD
                        
                                '///////////////////////////////////////////////////////////////////////////
                                ' ORIGINAL VARIABLES
                                '     IMFTopology *pTopology _    '// Topology.
                                '   , IMFActivate *pActivate _    '// Media sink activation object.    DOES NOT MATCH
                                '   , BYVAL dwId AS DWORD _       '// Identifier of the stream sink.   DOES NOT MATCH
                                '   , IMFTopologyNode **ppNode _  '// Receives the node pointer.
                                '///////////////////////////////////////////////////////////////////////////
                                '// Add an output node to a topology.
                                METHOD AddOutputNode( _
                                     BYVAL pTopology AS IMFTopology _                   ' __in IMFTopology *pTopology           '// Topology.
                                   , BYVAL pActivate AS IMFActivate _   DNM in not out  ' __out IMFActivate **ppEnablerActivate '// Media sink activation object.
                                   , BYVAL dwId AS DWORD _                        DNM   ' __in MFSequencerElementId dwId        '// Identifier of the stream sink.
                                   , BYREF ppNode AS IMFTopologyNode _                  ' __out IMFTopologyNode **ppNode        '// Receives the node pointer.
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pNode AS IMFTopologyNode
                                    'IMFTopologyNode *pNode = NOTHING
                        
                                    '// Create the node.
                                    hr = MFCreateTopologyNode(%MF_TOPOLOGY_OUTPUT_NODE, pNode)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Set the object pointer.
                                    hr = pNode.SetObject(pActivate)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Set the stream sink ID attribute.
                                    hr = pNode.SetUINT32($MF_TOPONODE_STREAMID, dwId)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    hr = pNode.SetUINT32($MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, %FALSE)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Add the node to the topology.
                                    hr = pTopology.AddNode(pNode)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    ''// Return the pointer to the caller.
                                    '*ppNode = pNode
                                    '(*ppNode).AddRef()
                        
                                    ''// Return the pointer to the caller.
                                    IF ISOBJECT(pNode) THEN
                                        ppNode = pNode
                                    END IF
                        
                                done:
                                    SafeRelease(pNode)
                                    METHOD = hr
                                END METHOD
                        
                                '///////////////////////////////////////////////////////////////////////////
                                ' ORIGINAL VARIABLES
                                '     IMFTopology *pTopology _          '// Topology.
                                '   , IMFMediaSource *pSource _         '// Media source.
                                '   , IMFPresentationDescriptor *pPD _  '// Presentation descriptor.
                                '   , IMFStreamDescriptor *pSD _        '// Stream descriptor.   DOES NOT MATCH
                                '   , IMFTopologyNode **ppNode _        '// Receives the node pointer.
                                '///////////////////////////////////////////////////////////////////////////
                                '// Add a source node to a topology.
                                METHOD AddSourceNode( _
                                     BYVAL pTopology AS IMFTopology _                      ' __in IMFTopology *pTopology                    '// Topology.
                                   , BYVAL pMediaSource AS IMFMediaSource _                ' __in IMFMediaSource *pMediaSource              '// Media source.
                                   , BYVAL pPD AS IMFPresentationDescriptor _              ' __in IMFPresentationDescriptor *pPD            '// Presentation descriptor.
                                   , BYVAL pSD AS IMFStreamDescriptor _      DNM in not out' __out IMFStreamDescriptor **ppStreamDescriptor '// Stream descriptor.
                                   , BYREF ppNode AS IMFTopologyNode _                     ' __out IMFTopologyNode **ppNode                 '// Receives the node pointer.
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pNode AS IMFTopologyNode
                                    'IMFTopologyNode *pNode = NOTHING
                        
                                    '// Create the node.
                                    hr = MFCreateTopologyNode(%MF_TOPOLOGY_SOURCESTREAM_NODE, pNode)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Set the attributes.
                                    hr = pNode.SetUnknown($MF_TOPONODE_SOURCE, pMediaSource)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    hr = pNode.SetUnknown($MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    hr = pNode.SetUnknown($MF_TOPONODE_STREAM_DESCRIPTOR, pSD)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Add the node to the topology.
                                    hr = pTopology.AddNode(pNode)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    ''// Return the pointer to the caller.
                                    '*ppNode = pNode
                                    '(*ppNode).AddRef()
                        
                                    ''// Return the pointer to the caller.
                                    IF ISOBJECT(pNode) THEN
                                        ppNode = pNode
                                    END IF
                        
                                done:
                                    SafeRelease(pNode)
                                    METHOD = hr
                                END METHOD
                        
                                '///////////////////////////////////////////////////////////////////////////
                                ' ORIGINAL VARIABLES
                                '     IMFStreamDescriptor *pSourceSD _    '// Pointer to the stream descriptor.     DOES NOT MATCH
                                '   , hVideoWindow AS DWORD _             '// Handle to the video clipping window.
                                '   , IMFActivate **ppActivate _                                                    DOES NOT MATCH
                                '///////////////////////////////////////////////////////////////////////////
                                '//  Create an activation object for a renderer, based on the stream media type.
                                METHOD CreateMediaSinkActivate( _
                                     BYREF pSourceSD AS IMFStreamDescriptor _ DNM in not out' __out IMFStreamDescriptor **ppStreamDescriptor '// Pointer to the stream descriptor.
                                   , BYVAL hVideoWindow AS DWORD _                          ' HWND                                           '// Handle to the video clipping window.
                                   , BYREF ppEnablerActivate AS IMFActivate _           DNM ' __out IMFActivate **ppEnablerActivate
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pHandler AS IMFMediaTypeHandler
                                    LOCAL pActivate AS IMFActivate
                        
                                    'IMFMediaTypeHandler *pHandler = NOTHING
                                    'IMFActivate *pActivate = NOTHING
                        
                                    '// Get the media type handler for the stream.
                                    hr = pSourceSD.GetMediaTypeHandler(pHandler)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Get the major media type.
                                    LOCAL guidMajorType AS GUID
                                    'GUID guidMajorType
                                    hr = pHandler.GetMajorType(guidMajorType)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Create an IMFActivate object for the renderer, based on the media type.
                                    IF ($MFMediaType_Audio = guidMajorType) THEN
                                        '// Create the audio renderer.
                                        hr = MFCreateAudioRendererActivate(pActivate)
                                    ELSEIF ($MFMediaType_Video = guidMajorType) THEN
                                        '// Create the video renderer.
                                        hr = MFCreateVideoRendererActivate(hVideoWindow, pActivate)
                                    ELSE
                                        '// Unknown stream type.
                                        hr = %E_FAIL
                                        '// Optionally, you could deselect this stream instead of failing.
                                    END IF
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    ''// Return IMFActivate pointer to caller.
                                    '*ppActivate = pActivate
                                    '(*ppActivate).AddRef()
                        
                                    '// Return IMFActivate pointer to caller.
                                    IF ISOBJECT(pActivate) THEN
                                        ppEnablerActivate = pActivate
                                    END IF
                        
                                done:
                                    SafeRelease(pHandler)
                                    SafeRelease(pActivate)
                                    METHOD = hr
                                END METHOD
                        
                        
                        
                                '//  Add a topology branch for one stream.
                                '//
                                '//  For each stream, this function does the following:
                                '//
                                '//    1. Creates a source node associated with the stream.
                                '//    2. Creates an output node for the renderer.
                                '//    3. Connects the two nodes.
                                '//
                                '//  The media session will add any decoders that are needed.
                        
                                '///////////////////////////////////////////////////////////////////////////
                                ' ORIGINAL VARIABLES
                                '     IMFTopology *pTopology _        '// Topology.
                                '   , IMFMediaSource *pSource _       '// Media source.
                                '   , IMFPresentationDescriptor *pPD _'// Presentation descriptor.
                                '   , DWORD iStream _                 '// Stream index.
                                '   , BYVAL hVideoWnd AS DWORD _      '// Window for video playback.
                                '///////////////////////////////////////////////////////////////////////////
                                METHOD AddBranchToPartialTopology( _
                                     BYVAL pTopology AS IMFTopology _                   ' __in IMFTopology *pTopology         '// Topology.
                                   , BYVAL pMediaSource AS IMFMediaSource _             ' __in IMFMediaSource *pMediaSource   '// Media source.
                                   , BYVAL pPD AS IMFPresentationDescriptor _           ' __in IMFPresentationDescriptor *pPD '// Presentation descriptor.
                                   , BYVAL MyStreamIdx AS DWORD _                       ' __in ??????                         '// Stream index.
                                   , BYVAL hVideoWnd AS DWORD _                         'HWND ????                            '// Window for video playback.
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pSD AS IMFStreamDescriptor
                                    LOCAL pSinkActivate AS IMFActivate
                                    LOCAL pSourceNode AS IMFTopologyNode
                                    LOCAL pOutputNode AS IMFTopologyNode
                                    LOCAL fSelected AS LONG
                        
                                    'IMFStreamDescriptor *pSD = NOTHING
                                    'IMFActivate         *pSinkActivate = NOTHING
                                    'IMFTopologyNode     *pSourceNode = NOTHING
                                    'IMFTopologyNode     *pOutputNode = NOTHING
                                    fSelected = %FALSE
                                    'BOOL fSelected = %FALSE
                        
                                    hr = pPD.GetStreamDescriptorByIndex(MyStreamIdx, fSelected, pSD)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    IF (fSelected) THEN
                                        '// Create the media sink activation object.
                                        hr = pPlayer.CreateMediaSinkActivate(pSD, hVideoWnd, pSinkActivate)
                                        IF FAILED(hr) THEN
                                            GOTO done
                                        END IF
                        
                                        '// Add a source node for this stream.
                                        hr = pPlayer.AddSourceNode(pTopology, pMediaSource, pPD, pSD, pSourceNode)
                                        IF FAILED(hr) THEN
                                            GOTO done
                                        END IF
                        
                                        '// Create the output node for the renderer.
                                        hr = pPlayer.AddOutputNode(pTopology, pSinkActivate, 0, pOutputNode)
                                        IF FAILED(hr) THEN
                                            GOTO done
                                        END IF
                        
                                        '// Connect the source node to the output node.
                                        hr = pSourceNode.ConnectOutput(0, pOutputNode, 0)
                                    END IF
                                    '// else: If not selected, don't add the branch.
                        
                                done:
                                    SafeRelease(pSD)
                                    SafeRelease(pSinkActivate)
                                    SafeRelease(pSourceNode)
                                    SafeRelease(pOutputNode)
                                    METHOD = hr
                                END METHOD
                        
                        
                                   '////////////////////////////////////////////////
                                   ' ORIGINAL VARIABLES
                                   '  IMFMediaSource *pSource _
                                   ', IMFPresentationDescriptor *pPD _
                                   ', BYVAL hVideoWnd AS DWORD _
                                   ',IMFTopology **ppTopology _
                                   '////////////////////////////////////////////////
                                METHOD CreatePlaybackTopology( _
                                     BYVAL pMediaSource AS IMFMediaSource _     ' __in IMFMediaSource *pMediaSource
                                   , BYVAL pPD AS IMFPresentationDescriptor _   ' __in IMFPresentationDescriptor *pPD
                                   , BYVAL hVideoWnd AS DWORD _                 '???? HWND                              '// Video window.
                                   , BYVAL ppTopology AS IMFTopology _          ' __out_opt IMFTopology **ppTopology    '// Receives a pointer to the topology.
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pTopology AS IMFTopology
                                    LOCAL cSourceStreams AS DWORD
                                    LOCAL i AS DWORD
                        
                                    '// Create a new topology.
                                    hr = MFCreateTopology(pTopology)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Get the number of streams in the media source.
                                    hr = pPD.GetStreamDescriptorCount(cSourceStreams)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// For each stream, create the topology nodes and add them to the topology.
                                    FOR i = 0 TO cSourceStreams - 1 '(DWORD i = 0 i < cSourceStreams i++)
                                        hr = pPlayer.AddBranchToPartialTopology(pTopology, pMediaSource, pPD, i, hVideoWnd)
                                        IF FAILED(hr) THEN
                                            GOTO done
                                        END IF
                                    NEXT i
                        
                                    '// Return the IMFTopology pointer to the caller.
                                    '*ppTopology = pTopology
                                    '(*ppTopology).AddRef()
                        
                                    '// Return the IMFTopology pointer to the caller.
                                    ppTopology = pTopology
                                    'ppTopology.AddRef()
                        
                                done:
                                    SafeRelease(pTopology)
                                    METHOD = hr
                                END METHOD
                        
                        
                                METHOD CPlayer( _             'CPlayer method
                                     BYVAL hVideo AS DWORD _     ' HWND  hVideo
                                   , BYVAL hEvent AS DWORD _     ' HWND
                                   ) AS LONG
                        
                        '            pMediaSession(NULL)
                        '            pMediaSource(NULL)
                        '            pVideoDisplay(NULL)
                        '            m_hwndVideo(hVideo)
                        '            m_hwndEvent(hEvent)
                        '            m_state(%Closed)
                        '            m_hCloseEvent(NULL)
                        '            m_nRefCount(1)
                        '            pCallback(NULL)
                        
                                    SafeRelease(pMediaSession)
                                    SafeRelease(pMediaSource)
                                    SafeRelease(pVideoDisplay)
                                    m_hwndVideo = hVideo
                                    m_hwndEvent = hEvent
                                    m_state = %Closed
                                    CloseHandle(m_hCloseEvent)
                                    m_nRefCount = 1
                                    SafeRelease(pCallback)
                        
                                END METHOD
                        
                        
                                '// IUnknown methods
                        
                        '        METHOD QueryInterface( _                      'CPlayer method
                        '             REFIID riid _
                        '           , void** ppv _
                        '           ) AS LONG
                        '
                        '            STATIC CONST QITAB qit[] =
                        '            {
                        '                'example QITABENT(CClass, IPersistStream)
                        '                QITABENT(CPlayer, IMFAsyncCallback),
                        '                { 0 }
                        '            }
                        '            FUNCTION = QISearch(THIS, qit, riid, ppv)
                        '        END METHOD
                        
                        '        METHOD AddRef() AS LONG                                       'CPlayer method
                        '            method = InterlockedIncrement(m_nRefCount)
                        '        END METHOD
                        '
                        '        METHOD Release() AS LONG                                     'CPlayer method
                        '            LOCAL uCount AS LONG
                        '            uCount = InterlockedDecrement(m_nRefCount)      'ulong
                        '            IF (uCount = 0) THEN
                        '                'DELETE THIS     ??????
                        '            END IF
                        '            method = uCount
                        '        END METHOD
                        
                                METHOD StateCallback()                     'CPlayer method (void)  PROTECTED
                                    pPlayer.OnPlayerStateChange(m_state)
                                END METHOD
                        
                        
                                '//  Start playback from paused or stopped.
                                METHOD PlayIt() AS LONG                         'CPlayer Method PROTECTED
                        
                                    IF (m_state <> %Paused AND m_state <> %Stopped) THEN
                                        METHOD = %MF_E_INVALIDREQUEST
                                        GOTO done
                                    END IF
                                    IF (ISFALSE ISOBJECT(pMediaSession) OR ISFALSE ISOBJECT(pMediaSource)) THEN
                                        METHOD = %E_UNEXPECTED
                                        GOTO done
                                    END IF
                                    METHOD = pPlayer.StartPlayback()
                                done:
                                END METHOD
                        
                        
                                '//  Pause playback.
                                METHOD Pause() AS LONG              'CPlayer Method
                        
                                    LOCAL hr AS LONG
                                    IF (m_state <> %Started) THEN
                                        METHOD = %MF_E_INVALIDREQUEST
                                        GOTO done
                                    END IF
                                    IF (ISFALSE ISOBJECT(pMediaSession) OR ISFALSE ISOBJECT(pMediaSource)) THEN
                                        METHOD = %E_UNEXPECTED
                                        GOTO done
                                    END IF
                        
                                    hr = pMediaSession.Pause()
                                    IF (SUCCEEDED(hr)) THEN
                                        m_state = %Paused
                                        pPlayer.StateCallback()
                                    END IF
                        
                                    METHOD = hr
                                done:
                                END METHOD
                        
                                '// Stop playback.
                                METHOD StopIt() AS LONG                   'CPlayer Method
                        
                                    LOCAL hr AS LONG
                                    IF (m_state <> %Started AND m_state <> %Paused) THEN
                                        METHOD = %MF_E_INVALIDREQUEST
                                        GOTO done
                                    END IF
                                    IF (ISFALSE ISOBJECT(pMediaSession)) THEN
                                        METHOD = %E_UNEXPECTED
                                        GOTO done
                                    END IF
                        
                                    hr = pMediaSession.Stop()
                                    IF (SUCCEEDED(hr)) THEN
                                        m_state = %Stopped
                                        pPlayer.StateCallback()
                                    END IF
                                    METHOD = hr
                                done:
                                END METHOD
                        
                                '//  Repaint the video window. Call this method on WM_PAINT.
                        
                                METHOD Repaint() AS LONG               'CPlayer Method
                                    IF ISOBJECT(pVideoDisplay) THEN
                                        METHOD = pVideoDisplay.RepaintVideo()
                                    ELSE
                                        METHOD = %S_OK
                                    END IF
                                END METHOD
                        
                                '//  Resize the video rectangle.
                                '//
                                '//  Call this method if the size of the video window changes.
                        
                                METHOD ResizeVideo( _            'CPlayer Method
                                     BYVAL x_width AS WORD _
                                   , BYVAL y_height AS WORD _
                                   ) AS LONG
                        
                                    LOCAL rcDest AS RECT
                        
                                    IF ISOBJECT(pVideoDisplay) THEN
                                        '// Set the destination rectangle.
                                        '// Leave the default source rectangle (0,0,1,1).
                                        'RECT rcDest = { 0, 0, x_WIDTH, y_height }
                                        rcDest.nLeft = 0
                                        rcDest.nTop = 0
                                        rcDest.nRight = x_width
                                        rcDest.nBottom = y_height
                        
                                        METHOD = pVideoDisplay.SetVideoPosition($NUL, rcDest)
                                    ELSE
                                        METHOD = %S_OK
                                    END IF
                                END METHOD
                        
                        
                                     '/////////////////////////////////////
                                     'ORIGINAL VARIABLES
                                     'IMFMediaEvent *pEvent _
                                     '/////////////////////////////////////
                        
                                '//  Start playback from the current position.
                                METHOD StartPlayback() AS LONG                'CPlayer Method  PROTECTED
                        
                                    LOCAL hr AS LONG
                                    LOCAL varStart AS PROPVARIANT 'ANY
                                    'PROPVARIANT varStart
                        
                                    IF ISOBJECT(pMediaSession) THEN ' <> %NULL     '?????  assert( pMediaSession != NULL)
                                        PropVariantInit(varStart)
                        
                                        hr = pMediaSession.Start($GUID_NULL, varStart)
                                        IF (SUCCEEDED(hr)) THEN
                                            '// Note: Start is an asynchronous operation. However, we
                                            '// can treat our state as being already started. If Start
                                            '// fails later, we'll get an MESessionStarted event with
                                            '// an error code, and we will update our state then.
                                            m_state = %Started
                                            pPlayer.StateCallback()
                                        END IF
                                        PropVariantClear(varStart)
                                    END IF
                                    METHOD = hr
                                END METHOD
                        
                                METHOD OnTopologyStatus( _                  'CPlayer Method PROTECTED
                                     BYVAL pEvent AS IMFMediaEvent _
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL StatusX AS DWORD
                                    'UINT32 STATUS
                        
                                    hr = pEvent.GetUINT32($MF_EVENT_TOPOLOGY_STATUS, StatusX)
                                    IF (SUCCEEDED(hr) AND (StatusX = %MF_TOPOSTATUS_READY)) THEN
                                        SafeRelease(pVideoDisplay)
                        
                                        '// Get the IMFVideoDisplayControl interface from EVR. This call is
                                        '// expected to fail if the media file does not have a video stream.
                        
                                     '   MFGetService(pMediaSession, $MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(pVideoDisplay))  '(void) ?????????????????
                        
                                        hr = pPlayer.StartPlayback()
                                    END IF
                                    METHOD = hr
                                END METHOD
                        
                        
                                     '////////////////////////////////////
                                     'ORIGINAL VARIABLE
                                     'UINT_PTR pEventPtr _
                                     '////////////////////////////////////
                        
                                METHOD HandleEvent( _                 'CPlayer Method
                                     BYVAL pEventPtr AS DWORD _
                                   ) AS LONG
                        
                                    LOCAL hrStatus AS LONG
                                    LOCAL hr AS LONG
                        
                                    hrStatus = %S_OK
                                    LOCAL meType AS LONG
                                    meType = %MEUnknown
                                    'MediaEventType meType = %MEUnknown
                                    LOCAL pEvent AS IMFMediaEvent
                        
                        '            IMFMediaEvent *pEvent = (IMFMediaEvent*)pEventPtr        '??????????????????? unfinished
                        
                                    IF (ISFALSE ISOBJECT(pEvent)) THEN
                                        METHOD = %E_POINTER
                                    END IF
                        
                                    '// Get the event type.
                                    hr = pEvent.GetType(meType)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Get the event status. If the operation that triggered the event
                                    '// did not succeed, the status is a failure code.
                                    hr = pEvent.GetStatus(hrStatus)
                        
                                    '// Check if the async operation succeeded.
                                    IF (SUCCEEDED(hr) AND FAILED(hrStatus)) THEN
                                        hr = hrStatus
                                    END IF
                        
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    SELECT CASE meType
                                        CASE %MESessionTopologyStatus
                                            hr = pPlayer.OnTopologyStatus(pEvent)
                        
                                        CASE %MEEndOfPresentation
                                            hr = pPlayer.OnPresentationEnded(pEvent)
                        
                                        CASE %MENewPresentation
                                            hr = pPlayer.OnNewPresentation(pEvent)
                        
                                        CASE ELSE
                                            hr = pPlayer.OnSessionEvent(pEvent, meType)
                                    END SELECT
                        
                                done:
                                    SafeRelease(pEvent)
                                    METHOD = hr
                                END METHOD
                        
                        
                                METHOD OnSessionEvent( _                 'CPlayer Method    CPlaylist
                                     BYVAL pEvent AS IMFMediaEvent _
                                   , BYVAL meType AS DWORD _
                                   ) AS LONG
                        
                                'HRESULT CPlaylist::OnSessionEvent(IMFMediaEvent *pEvent, MediaEventType meType)
                        
                                    IF (meType = %MESessionNotifyPresentationTime) THEN
                                        m_PresentationTimeOffset = MFGetAttributeUINT64(pEvent, $MF_EVENT_PRESENTATION_TIME_OFFSET, 0)
                                    END IF
                                    METHOD = %S_OK
                                END METHOD
                        
                        
                                '/// Protected methods
                        
                                     '///////////////////////////////
                                     'ORIGINAL VARIABLES
                                     'IMFMediaEvent* /*pEvent*/ _
                                     '///////////////////////////////
                        
                                '//  Handler for MEEndOfPresentation event.
                                METHOD OnPresentationEnded( _                    'CPlayer Method PROTECTED
                                     BYVAL pEvent AS IMFMediaEvent _
                                   ) AS LONG
                        
                                    '// The session puts itself into the stopped state automatically.
                                    m_state = %Stopped
                                    pPlayer.StateCallback()
                                    METHOD = %S_OK
                                END METHOD
                        
                                   '//////////////////////////////////////////////////////////
                                   ' ORIGINAL VARIABLES
                                   '  IMFMediaEvent *pEvent _
                                   ', Q **ppObject _
                                   '//////////////////////////////////////////////////////////
                        
                                METHOD GetEventObject( _
                                     BYVAL pEvent AS IMFMediaEvent _                    ' __in IMFMediaEvent *pEvent
                                   , BYREF ppObject AS IUNKNOWN _                   DNM  ' __out IUnknown **ppObject
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL varx AS PROPVARIANT 'ANY
                                    'PROPVARIANT varx
                        
                                    SafeRelease(ppObject)   '// zero output
                                    '*ppObject = NULL   '// zero output
                        
                                    hr = pEvent.GetValue(varx)
                                    IF (SUCCEEDED(hr)) THEN
                                        IF (varx.vt = %VT_UNKNOWN) THEN
                                            ? "here 01"
                                        '    hr = varx.punkVal.QueryInterface(ppObject)    '????????????????
                                        ELSE
                                            hr = %MF_E_INVALIDTYPE
                                        END IF
                                        PropVariantClear(varx)
                                    END IF
                                    METHOD = hr
                                END METHOD
                        
                                '//  Handler for MENewPresentation event.
                                '//
                                '//  This event is sent if the media source has a new presentation, which
                                '//  requires a new topology.
                                     '//////////////////////////////////////
                                     'ORIGINAL VARIABLES
                                     'IMFMediaEvent *pEvent _
                                     '//////////////////////////////////////
                        
                                METHOD OnNewPresentation( _                        'CPlayer Method protected
                                     BYVAL pEvent AS IMFMediaEvent _                    ' __in IMFMediaEvent *pEvent
                                   ) AS LONG
                        
                                    LOCAL hr AS LONG
                                    LOCAL pPD AS IMFPresentationDescriptor
                                    'IMFPresentationDescriptor *pPD = NOTHING
                                    LOCAL pTopology AS IMFTopology
                        
                                    '// Get the presentation descriptor from the event.
                                    hr = pPlayer.GetEventObject(pEvent, pPD)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Create a partial topology.
                                    hr = pPlayer.CreatePlaybackTopology(pMediaSource, pPD,  m_hwndVideo,pTopology)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Set the topology on the media session.
                                    hr = pMediaSession.SetTopology(0, pTopology)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    m_state = %OpenPending
                                    pPlayer.StateCallback()
                                done:
                                    SafeRelease(pTopology)
                                    SafeRelease(pPD)
                                    METHOD = %S_OK
                                END METHOD
                        
                        
                                '//  Close the media session.
                                METHOD CloseSession() AS LONG                    'CPlayer Method PROTECTED
                        
                                    '//  The IMFMediaSession::Close method is asynchronous, but the
                                    '//  CPlayer::CloseSession method waits on the MESessionClosed event.
                                    '//
                                    '//  MESessionClosed is guaranteed to be the last event that the
                                    '//  media session fires.
                        
                                    LOCAL hr AS LONG
                                    hr = %S_OK
                        
                                    SafeRelease(pVideoDisplay)
                        
                                    '// First close the media session.
                                    IF ISOBJECT(pMediaSession) THEN
                                        LOCAL dwWaitResult AS DWORD
                                        'DWORD dwWaitResult = 0
                        
                                        m_state = %Closing
                                        pPlayer.StateCallback()
                        
                                        hr = pMediaSession.Close()
                                        '// Wait for the close operation to complete
                                        IF (SUCCEEDED(hr)) THEN
                                            dwWaitResult = WaitForSingleObject(m_hCloseEvent, 5000)
                                            IF (dwWaitResult = %WAIT_TIMEOUT) THEN
                                                'assert(FALSE)  ????
                                            END IF
                                            '// Now there will be no more events from this session.
                        
                                        END IF
                                    END IF
                        
                                    '// Complete shutdown operations.
                                    IF (SUCCEEDED(hr)) THEN
                                        '// Shut down the media source. (Synchronous operation, no events.)
                                        IF ISOBJECT(pMediaSource) THEN
                                            ? "made it here"
                                            pMediaSource.Shutdown()        'void
                                        END IF
                                        '// Shut down the media session. (Synchronous operation, no events.)
                                        IF ISOBJECT(pMediaSession) THEN
                                            pMediaSession.Shutdown()       'void
                                        END IF
                                    END IF
                        
                                    'SafeRelease(pMediaSource)
                                    pMediaSource = NOTHING
                                    pMediaSession = NOTHING
                                    m_state = %Closed
                                    pPlayer.StateCallback()
                        
                                    METHOD = hr
                                    SessionStatus = "Media Session is closed."
                                    SourceStatus = "No Source created."
                                END METHOD
                        
                        
                                '//  Create a new instance of the media session.
                                METHOD OpenSession() AS LONG           'CPlayer Method  PROTECTED
                        
                                    LOCAL hr           AS LONG
                                    LOCAL punkState    AS IUNKNOWN
                        
                                    '// Close the old session, if any.
                                    'hr = pPlayer.CloseSession()
                                    'IF FAILED(hr) THEN
                                    '    GOTO done
                                    'END IF
                        
                                    m_state = %Closed
                                    pConfiguration = NOTHING
                        
                                    '// Create the media session.
                                    hr = MFCreateMediaSession(pConfiguration, pMediaSession)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Start pulling events from the media session
                                    '// For all other events, get the next event in the queue.
                                    'After the session has been created, you need to specify a
                                    'callback object that will receive asynchronous events
                                    'from the session.
                                    IF ISOBJECT(pMediaSession) THEN
                                        hr = pMediaSession.BeginGetEvent(pCallback, punkState)
                                        IF FAILED(hr) THEN
                                            '? "The session events were not linked."
                                            GOTO done
                                        END IF
                        
                                        m_state = %Ready
                        
                                        '? "The events were linked to the session."
                                    END IF
                        
                                    m_state = %Ready
                                    pPlayer.StateCallback()
                        
                                    SessionStatus = "Media Session is open."
                                done:
                                    METHOD = hr
                                END METHOD
                        
                                '' ============================== EXAMPLE ==============================================
                                'METHOD CreateInstance( _                             ' VTable offset = 64
                                '  BYVAL pUnkOuter AS IUnknown _                      ' __in IUnknown *pUnkOuter
                                ', BYREF riid AS GUID _                               ' __in REFIID riid
                                ', BYREF ppvObj AS IUnknown _                         ' __out PVOID *ppvObj
                                ') AS LONG                                            ' HRESULT
                                '' =====================================================================================
                                '//  Static class method to create the CPlayer object.
                        '        METHOD CreateInstance( _           'CPlayer method
                        '             BYVAL hVideo AS DWORD _       '// IN HWND Video window.
                        '           , BYVAL hEvent AS DWORD _       '// IN HWND Window to receive notifications.
                        '           , BYVAL ppPlayer AS IMFAsyncCallbackImpl _   '???? '// OUT CPlayer **ppPlayer Receives a pointer to the CPlayer object.
                        '           ) AS LONG
                        '
                        '            LOCAL hr AS LONG
                        '            IF (ISFALSE ISOBJECT(ppPlayer)) THEN
                        '                METHOD = %E_POINTER
                        '            END IF
                        '
                        '            '  CPlayer *pPlayer = NEW (std::nothrow) CPlayer(hVideo, hEvent)   ?????????????
                        '            IF (ISFALSE ISOBJECT(pPlayer)) THEN
                        '                METHOD = %E_OUTOFMEMORY
                        '            END IF
                        '
                        '            hr = ME.Create()   'Initialize()
                        '            IF (SUCCEEDED(hr)) THEN
                        '                ppPlayer = pPlayer
                        '            ELSE
                        '                pPlayer.Release()
                        '            END IF
                        '            METHOD = hr
                        '        END METHOD
                        
                        
                                'METHOD SetStateCallback( _                        'CPlayer method (void) PROTECTED
                                '     WebmMfUtil::MfPlayerCallback* ptr_callback)    '????????
                                '
                                '    pCallback = ptr_callback
                                'END METHOD
                        
                                     '///////////////////////////////////////////
                                     'ORIGINAL VARIABLE
                                     'CONST WCHAR *sURL _
                                     '///////////////////////////////////////////
                        
                                '//  Open a URL for playback.
                                METHOD OpenURL( _                        'CPlayer Method
                                     BYREF psURL AS WSTRINGZ _           ' const WCHAR *sURL
                                   ) AS LONG
                        
                                    '// 1. Create a new media session.
                                    '// 2. Create the media source.
                                    '// 3. Create the topology.
                                    '// 4. Queue the topology [asynchronous]
                                    '// 5. Start playback [asynchronous - does not happen in this method.]
                        
                                    LOCAL hr AS LONG
                                    LOCAL pTopology AS IMFTopology
                                    LOCAL pSourcePD AS IMFPresentationDescriptor
                                    'IMFPresentationDescriptor* pSourcePD = NOTHING
                        
                                    '// Create the media session.
                                    hr = pPlayer.OpenSession()
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Create the media source.
                                    hr = pPlayer.OpenMyMediaSource(psURL, pMediaSource)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Create the presentation descriptor for the media source.
                                    hr = pMediaSource.CreatePresentationDescriptor(pSourcePD)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Create a partial topology.
                                    hr = pPlayer.CreatePlaybackTopology(pMediaSource, pSourcePD, m_hwndVideo, pTopology)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    '// Set the topology on the media session.
                                    hr = pMediaSession.SetTopology(0, pTopology)
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                        
                                    m_state = %OpenPending
                                    pPlayer.StateCallback()
                        
                                    '// If SetTopology succeeds, the media session will queue an
                                    '// MESessionTopologySet event.
                        
                                done:
                                    IF FAILED(hr) THEN
                                        m_state = %Closed
                                        pPlayer.StateCallback()
                                    END IF
                        
                                    SafeRelease(pSourcePD)
                                    SafeRelease(pTopology)
                                    METHOD = hr
                                END METHOD
                        
                                METHOD onPlayerStateChange(BYVAL eventx AS LONG) AS LONG
                                '    Closed = 0     '// No session.
                                '    Ready          '// Session was created, ready to open a file.
                                '    OpenPending    '// Session is opening a file.
                                '    Started        '// Session is playing a file.
                                '    Paused         '// Session is paused.
                                '    Stopped        '// Session is stopped (ready to play).
                                '    Closing        '// Application has closed the session, but is waiting for MESessionClosed.
                        
                                    IF(eventx = 0) THEN
                                        SSMessages =  "The Session is closed." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "No session."
                                    END IF
                        
                                    IF(eventx = 1) THEN
                                        SSMessages = "The Session is open." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Session was created, ready to open a file."
                                    END IF
                        
                                    IF(eventx = 2) THEN
                                        SSMessages = "Session is opening a file." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Session is opening a file."
                                    END IF
                        
                                    IF(eventx = 3) THEN
                                        SSMessages = "Session is playing a file." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Session is playing a file."
                                    END IF
                        
                                    IF(eventx = 4) THEN
                                        SSMessages = "Session is paused." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Session is paused."
                                    END IF
                        
                                    IF(eventx = 5) THEN
                                        SSMessages = "Session is stopped (ready to play)." + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Session is stopped (ready to play)."
                                    END IF
                        
                                    IF(eventx = 6) THEN
                                        SSMessages = "The session is closing."  + $CRLF + SSMessages
                                        CONTROL SET TEXT hDlg, %TextboxText, SSMessages
                                        '? "Application has closed the session, but is waiting for MESessionClosed."
                                    END IF
                                    METHOD = eventx
                                END METHOD
                        
                            END INTERFACE
                        END CLASS
                        
                        
                        
                        
                        'SUB PropVariantinit (BYREF p AS PROPVARIANT)
                        '   ZeroMemory(BYVAL VARPTR(p), SIZEOF(PROPVARIANT))
                        'END SUB
                        
                        
                        '_________________________________________________________________
                        '
                        ' FileExists - make sure a file or folder exists
                        '_________________________________________________________________
                        
                        FUNCTION FileExists(sFileName AS ASCIIZ) AS LONG
                            LOCAL sFN AS STRING
                            sFN = REMOVE$(sFileName, $CRLF)
                            FUNCTION = PathFileExists(BYVAL STRPTR(sFN)) 'Return non-zero if file or folder exist.
                        
                        END FUNCTION
                        
                        '_________________________________________________________________
                        '
                        ' FileNam Get file name part of given path & name
                        '_________________________________________________________________
                        
                        FUNCTION FileNam (BYVAL Src AS STRING) AS STRING
                            LOCAL x AS LONG
                        
                            x = INSTR(-1, Src, ANY ":/\")
                            IF x THEN
                                FUNCTION = MID$(Src, x + 1)
                            ELSE
                                FUNCTION = Src
                            END IF
                        
                        END FUNCTION
                        
                        
                        
                        CLASS CMFAsyncCallback AS COM
                        
                        INTERFACE IMFAsyncCallback $IID_IMFAsyncCallback
                        
                            INHERIT IUNKNOWN
                        
                            '//////////////////////////////////////////////////////////////////////////////////////
                            '// These are Public methods
                            '//////////////////////////////////////////////////////////////////////////////////////
                            ' =====================================================================================
                            '// IMFAsyncCallback methods
                            ' =====================================================================================
                            METHOD GetParameters ( _                             ' VTable offset = 12
                              BYREF pdwFlags AS DWORD _                          ' __out DWORD *pdwFlags
                            , BYREF pdwQueue AS DWORD _                          ' __out DWORD *pdwQueue
                            ) AS LONG                                            ' HRESULT
                            END METHOD
                            ' =====================================================================================
                            METHOD Invoke ( _                                    ' VTable offset = 16
                              BYVAL pAsyncResult AS IMFAsyncResult _             ' __in IMFAsyncResult *pAsyncResult
                            ) AS LONG                                            ' HRESULT
                            '/////////////////////////////////////////////////////
                            ' ORIGINAL VARIABLES
                            '     IMFAsyncResult *pResult _
                            '/////////////////////////////////////////////////////
                            '//  Callback for the asynchronous BeginGetEvent method.
                            'PART OF IMFAsyncCallback
                            'METHOD Invoke( _                            'CPlayer Method
                            '     BYVAL pResult AS IMFAsyncResult _                  ' __in IMFAsyncResult *pResult
                            '   ) AS LONG
                            '
                                '? "Invoke"
                        
                                LOCAL hr AS LONG
                                LOCAL meType AS LONG 'MediaEventType
                                LOCAL pEvent AS IMFMediaEvent
                        
                                'MediaEventType meType = %MEUnknown  '// Event type       ???
                                'IMFMediaEvent *pEvent = NOTHING
                                meType = %MEUnknown  '// Event type       ???
                        
                                '// Get the event from the event queue.
                                hr = pMediaSession.EndGetEvent(pAsyncResult, pEvent)
                                IF FAILED(hr) THEN
                                    GOTO done
                                END IF
                        
                                '// Get the event type.
                                hr = pEvent.GetType(meType)
                                IF FAILED(hr) THEN
                                    GOTO done
                                END IF
                        
                                IF (meType = %MESessionClosed) THEN
                                    '// The session was closed.
                                    '// The application is waiting on the m_hCloseEvent event handle.
                                    '// Sets the specified event object to the signaled state.
                                    SetEvent(m_hCloseEvent)
                                ELSE
                                    '' =====================================================================================
                                    'METHOD BeginGetEvent ( _                             ' VTable offset = 16
                                    '  BYVAL pCallback AS IMFAsyncCallback _              ' __in IMFAsyncCallback *pCallback
                                    ', BYVAL punkState AS IUnknown _                      ' __in IUnknown *punkState
                                    ') AS LONG                                            ' HRESULT
                                    '' =====================================================================================
                                    'Reference found in:
                                    'IMFMediaSession
                                    'IMFMediaSource
                                    'IMFMediaStream
                                    'IMFStreamSink
                                    'IMFMediaEventQueue
                                    LOCAL punkState AS IUNKNOWN
                        
                                    '// For all other events, get the next event in the queue.
                                    hr = pMediaSession.BeginGetEvent(pCallback, punkState)            '(THIS, %NULL) ?????
                                    IF FAILED(hr) THEN
                                        GOTO done
                                    END IF
                                END IF
                        
                                '// Check the application state.
                        
                                '// If a call to IMFMediaSession::Close is pending, it means the
                                '// application is waiting on the m_hCloseEvent event and
                                '// the application's message loop is blocked.
                        
                                '// Otherwise, post a private window message to the application.
                        
                                IF (m_state <> %Closing) THEN
                                    '// Leave a reference count on the event.
                                    pEvent.AddRef()
                        
                                    'PostMessage(m_hwndEvent, %WM_APP_PLAYER_EVENT, pEvent, meType) '(WPARAM)pEvent, (LPARAM)meType)   '?????????????
                                    'CONTROL SEND CBHNDL, %TrackbarSpeed, %TBM_SETPOS, pEvent, meType  'Set initial position
                                    CONTROL SEND hDlg, %WM_APP_PLAYER_EVENT, %BM_CLICK, %NULL, meType
                                END IF
                        
                            done:
                                SafeRelease(pEvent)
                                METHOD = %S_OK
                            END METHOD
                        
                        END INTERFACE
                        
                        END CLASS
                        
                        
                        '_________________________________________________________________
                        '
                        ' SUB SetButtonFocus(hDlgName, %ID_SELECTEDBUTTON, %ID_DEFAULTBUTTON)
                        '_________________________________________________________________
                        
                        SUB SetButtonFocus(BYVAL hDlgName AS DWORD, AAA AS INTEGER, BBB AS INTEGER)
                        
                          CONTROL SEND hDlgName, AAA, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
                          CONTROL SET FOCUS hDlgName, BBB
                          CONTROL SEND hDlgName, BBB, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
                        
                        END SUB
                        
                        
                        ' ########################################################################################
                        ' Interface name = IMFMediaSource
                        ' IID = 279A808D-AEC7-40C8-9C6B-A6B492C78A66
                        ' Inherited interface = IMFMediaEventGenerator
                        ' ########################################################################################
                        
                        '#IF NOT %DEF(%IMFMediaSource_INTERFACE_DEFINED)
                        '    %IMFMediaSource_INTERFACE_DEFINED = 1
                        '
                        '$IID_IMFMediaSource = GUID$("{279A808D-AEC7-40C8-9C6B-A6B492C78A66}")
                        '
                        INTERFACE IMFMediaSource $IID_IMFMediaSource
                        
                           INHERIT IUNKNOWN
                        
                           ' =====================================================================================
                           ' IMFMediaEventGenerator methods
                           ' =====================================================================================
                           METHOD GetEvent ( _                                  ' VTable offset = 12
                             BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYREF ppEvent AS IMFMediaEvent _                   ' __out IMFMediaEvent **ppEvent
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD BeginGetEvent ( _                             ' VTable offset = 16
                             BYVAL pCallback AS IMFAsyncCallback _              ' __in IMFAsyncCallback *pCallback
                           , BYVAL punkState AS IUNKNOWN _                      ' __in IUnknown *punkState
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD EndGetEvent ( _                               ' VTable offset = 20
                             BYVAL pResult AS IMFAsyncResult _                  ' __in IMFAsyncResult *pResult
                           , BYREF ppEvent AS IMFMediaEvent _                   ' __out IMFMediaEvent **ppEvent
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD QueueEvent ( _                                ' VTable offset = 24
                             BYVAL met AS DWORD _                               ' __in MediaEventType met
                           , BYREF guidExtendedType AS GUID _                   ' __in REFGUID guidExtendedType
                           , BYVAL hrStatus AS LONG _                           ' __in HRESULT hrStatus
                           , BYREF pvValue AS PROPVARIANT _                     ' __in const PROPVARIANT *pvValue
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                        
                           ' =====================================================================================
                           ' IMFMediaSource methods
                           ' =====================================================================================
                           METHOD GetCharacteristics ( _                        ' VTable offset = 28
                             BYREF pdwCharacteristics AS DWORD _                ' __out DWORD *pdwCharacteristics
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD CreatePresentationDescriptor ( _              ' VTable offset = 32
                             BYREF ppPresentationDescriptor AS IMFPresentationDescriptor _ ' __out IMFPresentationDescriptor **ppPresentationDescriptor
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD Start ( _                                     ' VTable offset = 36
                             BYVAL pPresentationDescriptor AS IMFPresentationDescriptor _ ' __in IMFPresentationDescriptor *pPresentationDescriptor
                           , BYREF pguidTimeFormat AS GUID _                    ' __in const GUID *pguidTimeFormat
                           , BYREF pvarStartPosition AS PROPVARIANT _           ' __in const PROPVARIANT *pvarStartPosition
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD STOP ( _                                      ' VTable offset = 40
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD Pause ( _                                     ' VTable offset = 44
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD Shutdown ( _                                  ' VTable offset = 48
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                        
                        END INTERFACE
                        
                        
                        ' ########################################################################################
                        ' Interface name = IMFSourceResolver
                        ' IID = FBE5A32D-A497-4b61-BB85-97B1A848A6E3
                        ' Inherited interface = IUnknown
                        ' ########################################################################################
                        
                        '#IF NOT %DEF(%IMFSourceResolver_INTERFACE_DEFINED)
                        '    %IMFSourceResolver_INTERFACE_DEFINED = 1
                        '
                        '$IID_IMFSourceResolver = GUID$("{FBE5A32D-A497-4b61-BB85-97B1A848A6E3}")
                        
                        INTERFACE IMFSourceResolver $IID_IMFSourceResolver
                        
                           INHERIT IUNKNOWN
                        
                           ' =====================================================================================
                           METHOD CreateObjectFromURL ( _                       ' VTable offset = 12
                             BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                           , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                           , BYVAL pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                           , BYREF ppObject AS IUNKNOWN _                       ' __out IUnknown **ppObject
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD CreateObjectFromByteStream ( _                ' VTable offset = 16
                             BYVAL pByteStream AS IMFByteStream _               ' __in IMFByteStream *pByteStream
                           , BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                           , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                           , BYREF pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                           , BYREF ppObject AS IUNKNOWN _                       ' __out IUnknown **ppObject
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD BeginCreateObjectFromURL ( _                  ' VTable offset = 20
                             BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                           , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                           , BYREF ppIUnknownCancelCookie AS IUNKNOWN _         ' __out IUnknown **ppIUnknownCancelCookie
                           , BYVAL pCallback AS IMFAsyncCallback _              ' __in IMFAsyncCallback *pCallback
                           , BYVAL punkState AS IUNKNOWN _                      ' __in IUnknown *punkState
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD EndCreateObjectFromURL ( _                    ' VTable offset = 24
                             BYVAL pResult AS IMFAsyncResult _                  ' __in IMFAsyncResult *pResult
                           , BYREF pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                           , BYREF ppObject AS IUNKNOWN _                       ' __out IUnknown **ppObject
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD BeginCreateObjectFromByteStream ( _           ' VTable offset = 28
                             BYVAL pByteStream AS IMFByteStream _               ' __in IMFByteStream *pByteStream
                           , BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                           , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                           , BYREF ppIUnknownCancelCookie AS IUNKNOWN _         ' __out IUnknown **ppIUnknownCancelCookie
                           , BYVAL pCallback AS IMFAsyncCallback _              ' __in IMFAsyncCallback *pCallback
                           , BYVAL punkState AS IUNKNOWN _                      ' __in IUnknown *punkState
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD EndCreateObjectFromByteStream ( _             ' VTable offset = 32
                             BYVAL pResult AS IMFAsyncResult _                  ' __in IMFAsyncResult *pResult
                           , BYREF pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                           , BYREF ppObject AS IUNKNOWN _                       ' __out IUnknown **ppObject
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD CancelObjectCreation ( _                      ' VTable offset = 36
                             BYVAL pIUnknownCancelCookie AS IUNKNOWN _          ' __in IUnknown *pIUnknownCancelCookie
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                        
                        END INTERFACE
                        
                        
                        ' ########################################################################################
                        ' Interface name = IMFSchemeHandler
                        ' IID = 6D4C7B74-52A0-4BB7-B0DB-55F29F47A668
                        ' Inherited interface = IUnknown
                        ' ########################################################################################
                        
                        '#IF NOT %DEF(%IMFSchemeHandler_INTERFACE_DEFINED)
                            %IMFSchemeHandler_INTERFACE_DEFINED = 1
                        
                        '$IID_IMFSchemeHandler = GUID$("{6D4C7B74-52A0-4BB7-B0DB-55F29F47A668}")
                        
                        INTERFACE IMFSchemeHandler $IID_IMFSchemeHandler
                        
                           INHERIT IUNKNOWN
                        
                           ' =====================================================================================
                           METHOD BeginCreateObject ( _                         ' VTable offset = 12
                             BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                           , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                           , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                           , BYREF ppIUnknownCancelCookie AS IUNKNOWN _         ' __out IUnknown **ppIUnknownCancelCookie
                           , BYVAL pCallback AS IMFAsyncCallback _              ' __in IMFAsyncCallback *pCallback
                           , BYVAL punkState AS IUNKNOWN _                      ' __in IUnknown *punkState
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD EndCreateObject ( _                           ' VTable offset = 16
                             BYVAL pResult AS IMFAsyncResult _                  ' __in IMFAsyncResult *pResult
                           , BYREF pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                           , BYREF ppObject AS IUNKNOWN _                       ' __out IUnknown **ppObject
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                           METHOD CancelObjectCreation ( _                      ' VTable offset = 20
                             BYVAL pIUnknownCancelCookie AS IUNKNOWN _          ' __in IUnknown *pIUnknownCancelCookie
                           ) AS LONG                                            ' HRESULT
                           ' =====================================================================================
                        
                        END INTERFACE

                        Comment


                        • #52

                          This is the Event Viewer for MediaFoundation-Platform -> Media Foundation Platform

                          MFStartup returned 0x0
                          Source Resolver Context(0x96efa0) Resolve C:\Users\Public\Music\Billy Idol\The Very Best of Billy Idol\05 Eyes Without a Face.mp3 flags 0x1
                          Query Media Source clsid {477ec299-1421-4bdd-971f-7ccb933f21ad} do not use: false.
                          Source Resolver Context(0x96efa0) Trying Scheme Handler "File Scheme Handler"
                          Source Resolver Context(0x96efa0) SchemeHandler Result 0x0
                          Query Media Source clsid {a82e50ba-8e92-41eb-9df2-433f50ec2993} do not use: false.
                          Source Resolver Context(0x96efa0) Trying Byte Scheme Handler CLSID("MP3 Byte Stream Handler")
                          Source Resolver Context(0x96efa0) Byte stream Handler Result 0x0

                          It stops there and crashes the program.

                          The next step would be:
                          Source Resolver Context(0x96efa0) Resolving file:///C:/Users/Public/Music/Billy%20Idol/The%20Very%20Best%20of%20Billy%20Idol/05%20Eyes%20Without%20a%20Face.mp3 returned 0x0

                          but it doesn't get there.

                          The program memory allocation goes from 1.6 MB to 3 MB and then crashes. So it appears that the stream Handler is reading the file and trying to resolve it.
                          Any ideas?


                          Last edited by Jim Fritts; 14 Jun 2018, 01:05 PM.

                          Comment


                          • #53
                            The Source Resolver cannot resolve anything. Not even a short wav file. What gives?

                            Now I'm trying CreateObjectFromByteStream but it will not compile insisting that the dwFlags Parameter mismatches definition.

                            Even though I assigned it as a local DWORD and your include MFIDL identifies it as a dword value. This is crazy.


                            ' =====================================================================================
                            METHOD CreateObjectFromByteStream ( _ ' VTable offset = 16
                            BYVAL pByteStream AS IMFByteStream _ ' __in IMFByteStream *pByteStream
                            , BYREF pwszURL AS WSTRINGZ _ ' __in LPCWSTR pwszURL
                            , BYVAL dwFlags AS DWORD _ ' __in DWORD dwFlags
                            , BYVAL pProps AS IPropertyStore _ ' __in IPropertyStore *pProps
                            , BYREF pObjectType AS LONG _ ' __out MF_OBJECT_TYPE *pObjectType
                            , BYREF ppObject AS IUnknown _ ' __out IUnknown **ppObject
                            ) AS LONG ' HRESULT
                            ' =====================================================================================

                            The compiler will not accept this %MF_RESOLUTION_MEDIASOURCE either...

                            Unbelievable!

                            As it turns out the dwFlags was a problem with my app. I switched over to another development app and dwFlags now is accepted by the compiler. Whew! Will attempt the CreateObjectFromByteStream again. Soon
                            Last edited by Jim Fritts; 15 Jun 2018, 05:09 PM.

                            Comment


                            • #54
                              Code:
                              ' METHOD CreateObjectFromURL ( _                       ' VTable offset = 12
                                          '   BYREF pwszURL AS WSTRINGZ _                        ' __in LPCWSTR pwszURL
                                          ' , BYVAL dwFlags AS DWORD _                           ' __in DWORD dwFlags
                                          ' , BYVAL pProps AS IPropertyStore _                   ' __in IPropertyStore *pProps
                                          ' , BYVAL pObjectType AS LONG _                        ' __out MF_OBJECT_TYPE *pObjectType
                                          ' , BYREF ppObject AS IUnknown _                       ' __out IUnknown **ppObject
                                          ' ) AS LONG                                            ' HRESULT
                              If this is how it's defined in whatever headers you're using, then it's wrong. That param should be byref otherwise the function will never return success.

                              Comment


                              • #55
                                I thought so too when I first looked at it. Jose' includes do not provide MF_OBJECT_TYPE per se only the values that are passed.
                                Code:
                                ' enum MF_OBJECT_TYPE
                                %MF_OBJECT_MEDIASOURCE = 0
                                %MF_OBJECT_BYTESTREAM  = %MF_OBJECT_MEDIASOURCE + 1
                                %MF_OBJECT_INVALID     = %MF_OBJECT_BYTESTREAM  + 1
                                EndCreateObjectFromURL which is an asynchronous method has it BYREF but that is the counterpart to BeginCreateObjectFromURL.

                                Sadly the asynchronous methods crash as well. At this point I am mentally challenged when it comes to creating a media source. No matter what I try it never works.

                                Too bad Jose' is not that interested. Allegedly.

                                Comment


                                • #56
                                  It is obvious that I did a mistake and that this parameter must be declared BYREF. It should also be obvious that you must pass a LONG variable that will receive ine of the MF_OBJECT_xxx values, not that you have to pass one of these values.

                                  > Too bad Jose' is not that interested. Allegedly.

                                  I said that I have no time to study all these interfaces and translate all that C++ code. If you were in the right track and only needed some help, I will help you willingly, but it is evident that you don't fully understand how to work with COM with PB and you're trying to do a literal translation of the C++ code.

                                  For example, why you're calling this function

                                  Code:
                                  FUNCTION SafeRelease(BYREF ppT AS IUNKNOWN) AS LONG
                                      IF ISOBJECT(ppT) THEN
                                          ppT.Release
                                          ppT = NOTHING
                                      END IF
                                  END FUNCTION
                                  SafeRelease(pMediaSource), etc.

                                  When you only need to use pMediaSource = NOTHING ?

                                  Do you know what setting an object variable to NOTHING does? I will tell you: to call the release method.

                                  Why are you implementing IMFAsyncCallbackImpl inside the CPLayer class, and without the correct GUID? Do you know how events sinks work?
                                  Forum: http://www.jose.it-berater.org/smfforum/index.php

                                  Comment


                                  • #57
                                    Sorry Jose' I know you are busy. I used the SafeRelease just in case I missed something by using = NOTHING. I had = NOTHING in the previous version. So far I have not found the CPlayer class GUID or IID. The invoke seems to work nicely when the Session is closed. I have to have a Source created to test it further. I used the IMFAsyncCallbackImpl for the CPlayer for no special reason. Like I said I am mentally challenged right now.

                                    I just needed your assurance that changing to BYREF was the right thing to do. Thank you.

                                    Yahoo!!!!
                                    The Media Source was created.

                                    Comment


                                    • #58
                                      This is a start, to show you how to translate the code. Read the comments.
                                      I haven't time to finish it. See if you can continue.
                                      Don't forget to modify CreateObjectFromURL in the "mfidl.inc" file.

                                      Code:
                                      #COMPILE EXE
                                      #DIM ALL
                                      %UNICODE = 1
                                      #INCLUDE ONCE "windows.inc"
                                      #INCLUDE ONCE "mfapi.inc"
                                      #INCLUDE ONCE "mfidl.inc"
                                      #INCLUDE ONCE "evr.inc"  'needed for video display control
                                      #INCLUDE ONCE "Mferror.inc"
                                      
                                      ENUM PlayerState  'm_state values
                                         Closed = 0     '// No session.
                                         Ready          '// Session was created, ready to open a file.
                                         OpenPending    '// Session is opening a file.
                                         Started        '// Session is playing a file.
                                         Paused         '// Session is paused.
                                         Stopped        '// Session is stopped (ready to play).
                                         Closing        '// Application has closed the session, but is waiting for MESessionClosed.
                                      END ENUM
                                      
                                      CLASS CPlayer
                                      
                                         INSTANCE m_pSession AS IMFMediaSession
                                         INSTANCE m_pSource AS IMFMediaSource
                                         INSTANCE m_pVideoDisplay AS IMFVideoDisplayControl
                                         INSTANCE m_hwndVideo AS DWORD
                                         INSTANCE m_hwndEvent AS DWORD
                                         INSTANCE m_state AS LONG
                                         INSTANCE m_hCloseEvent AS DWORD
                                      '   INSTANCE m_pContentProtectionManager AS IMFContentProtectionManager
                                      
                                         CLASS METHOD Create
                                         END METHOD
                                      
                                         CLASS METHOD Destroy
                                         END METHOD
                                      
                                         INTERFACE IPlayer : INHERIT IUnknown
                                      
                                         ' ///////////////////////////////////////////////////////////////////////
                                         ' //  Name: CreateInstance
                                         ' //  Description:  Static class method to create the CPlayer object.
                                         ' //  
                                         ' //  hVideo:   Handle to the video window.
                                         ' //  hEvent:   Handle to the window to receive notifications.
                                         ' //  ppPlayer: Receives an AddRef's pointer to the CPlayer object.
                                         ' //            The caller must release the pointer.
                                         ' /////////////////////////////////////////////////////////////////////////
                                         ' // Note: We create an instance of the class with
                                         ' // DIM pPlayer AS CPlayer : pPlayer = CLASS "CPlayer" and the PB class manages
                                         ' // automatically reference counting. Therefore all we need is to store the passed values
                                         ' // and call the Initialize method.
                                         METHOD CreateInstance (BYVAL hVideo AS DWORD, BYVAL hEvent AS DWORD) AS LONG
                                            m_hwndVideo = hVideo
                                            m_hwndEvent = hEvent
                                            m_state = %PlayerState.Ready
                                            METHOD = ME.Initialize
                                         END METHOD
                                      
                                         ' //////////////////////////////////////////////////////////////////////
                                         ' //  Name: Initialize
                                         ' //  Initializes the CPlayer object. This method is called by the
                                         ' //  CreateInstance method.
                                         ' /////////////////////////////////////////////////////////////////////////
                                      
                                         METHOD Initialize () AS LONG
                                            LOCAL hr AS LONG
                                            hr = %S_OK
                                            IF m_hCloseEvent THEN METHOD = %MF_E_ALREADY_INITIALIZED : EXIT METHOD
                                            ' // Start up Media Foundation platform.
                                            hr = MFStartup(%MF_VERSION, 0)
                                            IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                            m_hCloseEvent = CreateEventW(BYVAL %NULL, %FALSE, %FALSE, BYVAL %NULL)
                                            IF m_hCloseEvent = %NULL THEN
                                               METHOD = HRESULT_FROM_WIN32(GetLastError)
                                               EXIT METHOD
                                            END IF
                                            METHOD = hr
                                         END METHOD
                                      
                                         ' // Note: The C++ methods AddRef, Release and QueryInterface aren't needed in a PB class
                                      
                                      
                                         ' ///////////////////////////////////////////////////////////////////////
                                         ' //  Name: OpenURL
                                         ' //  Description:  Opens a URL for playback.
                                         ' /////////////////////////////////////////////////////////////////////////
                                      
                                         METHOD OpenURL(BYREF sURL AS WSTRINGZ) AS LONG
                                            ' // 1. Create a new media session.
                                            ' // 2. Create the media source.
                                            ' // 3. Create the topology.
                                            ' // 4. Queue the topology [asynchronous]
                                            ' // 5. Start playback [asynchronous - does not happen in this method.]
                                      
                                            LOCAL hr AS LONG
                                            LOCAL pTopology AS IMFTopology
                                      
                                            ' // Create the media session.
                                            hr = ME.CreateSession
                                            IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            ' // Create the media source.
                                            hr = ME.CreateMediaSource(sURL)
                                            IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            ' // Create a partial topology.
                                      '      hr = ME.CreateTopologyFromSource(pTopology)
                                      '      IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            ' // Set the topology on the media session.
                                      '      hr = ME.SetTopology(0, pTopology)
                                      '      IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            ' // Set our state to "open pending"
                                            m_state = %PlayerState.OpenPending
                                      
                                            METHOD = hr
                                      
                                         END METHOD
                                      
                                         ' ///////////////////////////////////////////////////////////////////////
                                         ' //  Name: CreateSession
                                         ' //  Description:  Creates a new instance of the media session.
                                         ' /////////////////////////////////////////////////////////////////////////
                                      
                                         METHOD CreateSession () AS LONG
                                            LOCAL hr AS LONG
                                            hr = %S_OK
                                      
                                            LOCAL pAttributes AS IMFAttributes
                                            LOCAL pEnablerActivate AS IMFActivate
                                      
                                            ' // Close the old session, if any.
                                      '      hr = ME.CloseSession
                                      '      IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            m_state = %PlayerState.Closed
                                      
                                            ' // Create a new attribute store.
                                            hr = MFCreateAttributes(pAttributes, 1)
                                            IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                           ' // *** The following code will need to write a ContentProtectionManager class ***
                                      '       // Create the content protection manager.
                                      '       assert(m_pContentProtectionManager == NULL); // Was released in CloseSession
                                      '       CHECK_HR(hr = ContentProtectionManager::CreateInstance(
                                      '               m_hwndEvent,
                                      '               &m_pContentProtectionManager
                                      '               ));
                                      '       // Set the MF_SESSION_CONTENT_PROTECTION_MANAGER attribute with a pointer
                                      '       // to the content protection manager.
                                      '       CHECK_HR(hr = pAttributes->SetUnknown(
                                      '               MF_SESSION_CONTENT_PROTECTION_MANAGER,
                                      '               (IMFContentProtectionManager*)m_pContentProtectionManager
                                      '               ));
                                      '       // Create the PMP media session.
                                      '       CHECK_HR(hr = MFCreatePMPMediaSession(
                                      '               0, // Can use this flag: MFPMPSESSION_UNPROTECTED_PROCESS
                                      '               pAttributes,
                                      '               &m_pSession,
                                      '               &pEnablerActivate
                                      '               ));
                                      
                                      '       // TODO:
                                      
                                      '       // If MFCreatePMPMediaSession fails it might return an IMFActivate pointer.
                                      '       // This indicates that a trusted binary failed to load in the protected process.
                                      '       // An application can use the IMFActivate pointer to create an enabler object, which
                                      '       // provides revocation and renewal information for the component that failed to
                                      '       // load.
                                      
                                      '       // This sample does not demonstrate that feature. Instead, we simply treat this
                                      '       // case as a playback failure.
                                      
                                      
                                      '       // Start pulling events from the media session
                                      '       CHECK_HR(hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL));
                                      
                                            METHOD = hr
                                      
                                         END METHOD
                                      
                                         ' ///////////////////////////////////////////////////////////////////////
                                         ' //  Name: CreateMediaSource
                                         ' //  Description:  Create a media source from a URL.
                                         ' //
                                         ' //  sURL: The URL to open.
                                         ' /////////////////////////////////////////////////////////////////////////
                                      
                                         METHOD CreateMediaSource(BYREF sURL AS WSTRINGZ) AS LONG
                                            LOCAL hr AS LONG
                                            hr = %S_OK
                                            LOCAL ObjectType AS LONG
                                            ObjectType = %MF_OBJECT_INVALID
                                      
                                            LOCAL pSourceResolver AS IMFSourceResolver
                                            LOCAL pSource AS IUnknown
                                      
                                            m_pSource = NOTHING
                                      
                                            ' // Create the source resolver.
                                            hr = MFCreateSourceResolver(pSourceResolver)
                                            IF hr <> %S_OK THEN METHOD = hr : EXIT METHOD
                                      
                                            ' // Use the source resolver to create the media source.
                                      
                                            ' // Note: For simplicity this sample uses the synchronous method on
                                            ' // IMFSourceResolver to create the media source. However, creating a
                                            ' // media source can take a noticeable amount of time, especially for
                                            ' // a network source. For a more responsive UI, use the asynchronous
                                            ' // BeginCreateObjectFromURL method.
                                      
                                            hr = pSourceResolver.CreateObjectFromURL ( _
                                                        sURL, _                        ' // URL of the source.
                                                        %MF_RESOLUTION_MEDIASOURCE, _  ' // Create a source object.
                                                        NOTHING, _                     ' // Optional property store.
                                                        ObjectType, _                  ' // Receives the created object type.
                                                        pSource _                      ' // Receives a pointer to the media source.
                                                     )
                                      
                                            ' // Get the IMFMediaSource interface from the media source.
                                            ' CHECK_HR(hr = pSource->QueryInterface(__uuidof(IMFMediaSource), (void**)&m_pSource));
                                            ' Note: When assigning an object variable to another, PB does an automatic call to QueryInterface
                                            m_pSource = pSource
                                      
                                            METHOD = hr
                                         END METHOD
                                      
                                         END INTERFACE
                                      
                                      END CLASS
                                      
                                      FUNCTION PBMAIN
                                         ? "Ok"
                                      END FUNCTION
                                      Forum: http://www.jose.it-berater.org/smfforum/index.php

                                      Comment


                                      • #59
                                        Excellent Thank you

                                        Comment


                                        • #60
                                          All,

                                          Historic Event! Today was the first time I was
                                          able to create a topology for my Media Foundation
                                          test app. This process took 22 days. I had to
                                          translate C/C++ code to PowerBasic source code.
                                          However, it is still not playing. I'll get there eventually.

                                          This book is every helpful...

                                          Developing Microsoft Media Foundation Applications

                                          The electronic version is online and free.

                                          Comment

                                          Working...
                                          X