It is currently Thu Aug 06, 2020 2:28 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Windows Media Player Control
PostPosted: Sat Jun 20, 2020 4:28 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 679
I prefer libvlc to play videos but here is an example of WMP Control that does not need the bloat of the libvlc dlls.

It was easy for me to translate the interfaces because i was writing a tool to import the typelib so it has been done automatically.

The are 3 files:
WMPlayer.OCX.pbi : The interface definitions, big file 104Kb.
wmp.pb : Small include of helper functions.
wmpTest.pb : A small working player.

I did not write any interface method wrapper, you will need to refer to the documentation:
https://docs.microsoft.com/en-us/windows/win32/wmp/object-model-reference-for-c
Look at wmpTest.pb for an easy example.

If i have time i will post how to handle events.

WMPlayer.OCX.pbi (104kb):
https://github.com/omegakode/WMPlayer
Click on Clone or Download to get the file.

EDIT:
Removed set/get userdata the regular Set/Get GadgetData() can be used.
Added stretchToFit by default when creating the control, so the video fills the control preserving aspect ratio.
Minor bug fixes.

wmp.pb helper:
Code:
IncludeFile "WMPlayer.OCX.pbi"

;Windows Media Player Functions
;Justin 06/2020

;https://docs.microsoft.com/en-us/windows/win32/wmp/windows-media-player-sdk

EnableExplicit

;- WINDOWS
;- VECTOR_VARIANT
Structure VECTOR_VARIANT
   var.VARIANT[0]
EndStructure

;- DISPPARAMS_
Structure DISPPARAMS_ Align #PB_Structure_AlignC
   *rgvarg.VECTOR_VARIANT
   rgdispidNamedArgs.i
   cArgs.l
   cNamedArgs.l
EndStructure

;- IUnknownVtbl
Structure IUnknownVtbl
   QueryInterface.i
   AddRef.i
   Release.i
EndStructure

;- IDispatchVtbl
Structure IDispatchVtbl Extends IUnknownVtbl
   GetIDsOfNames.i
   GetTypeInfo.i
   GetTypeInfoCount.i
   Invoke.i
EndStructure

;- IID_IDispatch
DataSection
   IID_IDispatch:
   Data.l $00020400
   Data.w $0000, $0000
   Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection

;- IID_IConnectionPointContainer
DataSection
   IID_IConnectionPointContainer:
   Data.l $B196B284
   Data.w $BAB4, $101A
   Data.b $B6, $9C, $00, $AA, $00, $34, $1D, $07
EndDataSection


;-wmp_EventCallback
;wmp: container gadget.
;dispid : #_WMPOCXEvents_dispid enum
;*params : event params in reversed order
Prototype wmp_EventCallback(wmp.i, dispid.l, *params.DISPPARAMS_)

;- WMP_EVENTS_OBJECT
Structure WMP_EVENTS_OBJ
   vt.i
   refCount.l
   *wmp.WMP_OBJECT
   evCallBack.wmp_EventCallback
EndStructure

Structure WMP_EVENTS_VT_TAG Extends IDispatchVtbl

EndStructure
Global.WMP_EVENTS_VT_TAG WMP_EVENTS_VT

;- WMP_OBJECT
Structure WMP_OBJECT
   container.i
   wmpPlayer.IWMPPlayer2
   wmpCore.IWMPCore
   wmpControls.IWMPControls
   oldContWndProc.i
   *events.WMP_EVENTS_OBJ
EndStructure

Procedure wmp_EvtNew(*wmp.WMP_OBJECT, evCallback.wmp_EventCallback)
   Protected.WMP_EVENTS_OBJ *this
   
   *this = AllocateMemory(SizeOf(WMP_EVENTS_OBJ))
   *this\vt = WMP_EVENTS_VT
   *this\wmp = *wmp
   *this\evCallBack = evCallback
   *this\refCount = 1
   
   ProcedureReturn *this
EndProcedure

Procedure wmp_EvtFree(*this.WMP_EVENTS_OBJ)
   FreeMemory(*this)
EndProcedure

Procedure wmp_EvtQueryInterface(*this.WMP_EVENTS_OBJ, *iid.IID, *obj.INTEGER)
   If CompareMemory(*iid, ?IID__WMPOCXEvents, SizeOf(IID)) Or CompareMemory(*iid, ?IID_IDispatch, SizeOf(IID))
      *obj\i = *this
      ProcedureReturn #S_OK
      
   Else
      *obj\i = #Null
      ProcedureReturn #E_NOINTERFACE
   EndIf
EndProcedure

Procedure wmp_EvtAddRef(*this.WMP_EVENTS_OBJ)
   *this\refCount = *this\refCount + 1
   
   ProcedureReturn *this\refCount
EndProcedure

Procedure wmp_EvtRelease(*this.WMP_EVENTS_OBJ)
   *this\refCount = *this\refCount - 1
   If *this\refCount = 0
      wmp_EvtFree(*this)
   EndIf
EndProcedure

Procedure wmp_EvtGetIDsOfNames(*this.WMP_EVENTS_OBJ, *iid.IID, rgszNames.i, cNames.l, lcid.l, rgDispId.i)
   ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure wmp_EvtGetTypeInfo(*this.WMP_EVENTS_OBJ, iTInfo.i, lcid.l, ppTInfo.i)
   ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure wmp_EvtGetTypeInfoCount(*this.WMP_EVENTS_OBJ, pctinfo.i)
   ProcedureReturn #E_NOTIMPL
EndProcedure

Procedure wmp_EvtInvoke(*this.WMP_EVENTS_OBJ, dispIdMember.l, *iid.IID, lcid.l, wFlags.w, pDispParams.i, *pVarResult.VARIANT, pExcepInfo.i, puArgErr.i)
   If *this\evCallBack
      *this\evCallBack(*this\wmp\container, dispIdMember, pDispParams)
   EndIf
EndProcedure

;- WMP_EVENTS_VT
WMP_EVENTS_VT\QueryInterface = @wmp_EvtQueryInterface()
WMP_EVENTS_VT\AddRef = @wmp_EvtAddRef()
WMP_EVENTS_VT\Release = @wmp_EvtRelease()
WMP_EVENTS_VT\GetIDsOfNames = @wmp_EvtGetIDsOfNames()
WMP_EVENTS_VT\GetTypeInfo = @wmp_EvtGetTypeInfo()
WMP_EVENTS_VT\GetTypeInfoCount = @wmp_EvtGetTypeInfoCount()
WMP_EVENTS_VT\Invoke = @wmp_EvtInvoke()

Macro wmp_GetObject(wmpId)
   GetWindowLongPtr_(GadgetID(wmpId), #GWLP_USERDATA)
EndMacro

Procedure wmp_ContOnDestroy(hwnd.i, msg.l, wparam.i, lparam.i)
   Protected.WMP_OBJECT *wmp = GetWindowLongPtr_(hwnd, #GWLP_USERDATA)
      
   If *wmp
      If *wmp\wmpControls : *wmp\wmpControls\Release() : EndIf
      If *wmp\wmpPlayer : *wmp\wmpPlayer\Release() : EndIf
      If *wmp\wmpCore : *wmp\wmpCore\Release() : EndIf
   
      If *wmp\events : wmp_EvtRelease(*wmp\events) : EndIf
         
      SetWindowLongPtr_(hwnd, #GWLP_WNDPROC, *wmp\oldContWndProc)

      FreeMemory(*wmp)
   EndIf
EndProcedure

Procedure wmp_ContOnDefault(hwnd.i, msg.l, wparam.i, lparam.i)
   Protected.WMP_OBJECT *wmp = GetWindowLongPtr_(hwnd, #GWLP_USERDATA)

   If *wmp
      ProcedureReturn CallWindowProc_(*wmp\oldContWndProc, hwnd, msg, wparam, lparam)
      
   Else
      ProcedureReturn DefWindowProc_(hwnd, msg, wparam, lparam)
   EndIf
EndProcedure

Procedure wmp_ContWndProc(hwnd.i, msg.l, wparam.i, lparam.i)
   Select msg
      Case #WM_DESTROY : ProcedureReturn wmp_ContOnDestroy(hwnd, msg, wparam, lparam)
      
      Default : ProcedureReturn wmp_ContOnDefault(hwnd.i, msg.l, wparam.i, lparam.i)
   EndSelect
EndProcedure

Procedure wmp_Create(id.i, x.i, y.i, width.i, height.i, evCallback.wmp_EventCallback = #Null)
   Protected.WMP_OBJECT *wmp
   Protected.IUnknown unkCont
   Protected.IConnectionPointContainer cpc
   Protected.IConnectionPoint  cp
   Protected.l cookie
   
   *wmp = AllocateMemory(SizeOf(WMP_OBJECT))
   *wmp\container = ContainerGadget(id, x, y, width, height)
   If *wmp\container
      If AtlAxCreateControl_("WMPlayer.OCX", GadgetID(*wmp\container), #Null, #Null) = #S_OK
         If AtlAxGetControl_(GadgetID(*wmp\container), @unkCont) = #S_OK
            If unkCont
               unkCont\QueryInterface(?IID_IWMPPlayer2, @*wmp\wmpPlayer)
               unkCont\QueryInterface(?IID_IWMPCore, @*wmp\wmpCore)
               unkCont\QueryInterface(?IID_IWMPControls, @*wmp\wmpControls)
               
               unkCont\Release()   
            EndIf
         EndIf
      EndIf
      
      If *wmp\wmpCore And *wmp\wmpPlayer And *wmp\wmpControls
         SetWindowLongPtr_(GadgetID(*wmp\container), #GWLP_USERDATA, *wmp)
         *wmp\oldContWndProc = SetWindowLongPtr_(GadgetID(*wmp\container), #GWLP_WNDPROC, @wmp_ContWndProc())
         
         *wmp\wmpPlayer\put_enableContextMenu(#VARIANT_FALSE)
         *wmp\wmpPlayer\put_enableContextMenu(#VARIANT_FALSE)
         *wmp\wmpPlayer\put_stretchToFit(#VARIANT_TRUE)

         ;Events
         If evCallback
            If *wmp\wmpPlayer\QueryInterface(?IID_IConnectionPointContainer, @cpc) = #S_OK
               If cpc\FindConnectionPoint(?IID__WMPOCXEvents, @cp) = #S_OK
                  *wmp\events = wmp_EvtNew(*wmp, evCallback)
                  cp\Advise(*wmp\events, @cookie)
                  cp\Release()
               EndIf
               
               cpc\Release()
            EndIf
         EndIf
         
         ProcedureReturn *wmp\container
         
      Else
         FreeMemory(*wmp)
         ProcedureReturn 0
      EndIf
   EndIf
EndProcedure

Procedure wmp_GetPlayer(wmpid.i)
   Protected.WMP_OBJECT *wmp = wmp_GetObject(wmpid)

   ProcedureReturn *wmp\wmpPlayer
EndProcedure

Procedure wmp_GetCore(wmpid.i)
   Protected.WMP_OBJECT *wmp = wmp_GetObject(wmpid)

   ProcedureReturn *wmp\wmpCore
EndProcedure

Procedure wmp_GetControls(wmpid.i)
   Protected.WMP_OBJECT *wmp = wmp_GetObject(wmpid)

   ProcedureReturn *wmp\wmpControls
EndProcedure


wmpTest.pb example
Code:
;Windows Media Player Example
;Justin 06/2020

XIncludeFile "wmp.pb"

EnableExplicit

Define.i ev
Global.i g_wmp, g_lastUIMode

Enumeration
   #MENU_ID_OPEN
   #MENU_ID_UI_NONE
   #MENU_ID_UI_MINI
   #MENU_ID_UI_FULL
   #MENU_ID_PLAY_PAUSE
   #MENU_ID_STOP
EndEnumeration

Procedure fileOpen()
   Protected.s file
   Protected.IWMPCore core = wmp_GetCore(g_wmp)
   Protected.WMP_OBJECT *wmp = wmp_GetObject(g_wmp)
   
   file = OpenFileRequester("Open", "", "", 0)
   If file
      core\put_URL(file)
      
;----------------- PB BUG ------------------------
;Calling a method with a bstr from inside a structure produces an IMA.
;*wmp\wmpCore\put_URL(file) ;   IMA
;-------------------------------------------------
   EndIf
EndProcedure

Procedure onResize()
   ResizeGadget(g_wmp, 0, 0, WindowWidth(0), WindowHeight(0) - MenuHeight())
EndProcedure

Procedure setUIMode(menId.l)
   Protected.IWMPPlayer2 player = wmp_GetPlayer(g_wmp)
   
   SetMenuItemState(0, g_lastUIMode, #False)
   
   Select menid
      Case #MENU_ID_UI_FULL
         player\put_uiMode("full")
         
      Case #MENU_ID_UI_MINI
         player\put_uiMode("mini")

      Case #MENU_ID_UI_NONE
         player\put_uiMode("none")
   EndSelect
   
   SetMenuItemState(0, menId, #True)
   g_lastUIMode = menId
EndProcedure

Procedure playPause()
   Protected.IWMPCore core = wmp_GetCore(g_wmp)
   Protected.IWMPControls controls = wmp_GetControls(g_wmp)
   Protected.l state
   
   core\get_playState(@state)
   If state = #wmppsPaused
      controls\play()
      
   ElseIf state = #wmppsPlaying
      controls\pause()
   EndIf
EndProcedure

Procedure stop()
   Protected.IWMPControls controls = wmp_GetControls(g_wmp)

   controls\stop()
EndProcedure

;*params are in reversed order.
Procedure eventCallback(wmp.i, dispid.l, *params.DISPPARAMS_)
   Select dispid
      Case #_WMPOCXEvents_dispid_PlayStateChange
         Debug "PlayStateChange " + Str(*params\rgvarg\var[0]\lVal)
   
      Case #_WMPOCXEvents_dispid_PositionChange
         Debug "PositionChange " + "old: " + StrD(*params\rgvarg\var[1]\dblVal) + " new: " + StrD(*params\rgvarg\var[0]\dblVal)
         
      Case #_WMPOCXEvents_dispid_Click
         Select *params\rgvarg\var[3]\iVal
            Case 1
               Debug "Left Click"
               
            Case 2
               Debug "Right Click"
               
            Case 4
               Debug "Middle Click"
         EndSelect
   EndSelect
EndProcedure

OpenWindow(0, 100, 150, 600, 400, "WMP", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
CreateMenu(0, WindowID(0))
MenuTitle("File")
MenuItem(#MENU_ID_OPEN, "Open...")
MenuTitle("Playback")
MenuItem(#MENU_ID_PLAY_PAUSE, "Play / Pause")
MenuItem(#MENU_ID_STOP, "Stop")

MenuTitle("View")
OpenSubMenu("UI Mode")
MenuItem(#MENU_ID_UI_NONE, "None")
MenuItem(#MENU_ID_UI_MINI, "Mini")
MenuItem(#MENU_ID_UI_FULL, "Full")
CloseSubMenu()
SetMenuItemState(0, #MENU_ID_UI_FULL, #True)
g_lastUIMode = #MENU_ID_UI_FULL

BindEvent(#PB_Event_SizeWindow, @onResize())

g_wmp = wmp_Create(#PB_Any, 0, 0, WindowWidth(0), WindowHeight(0) - MenuHeight(), @eventCallback())
If g_wmp = 0
   MessageRequester("Fatal error", "WMP could not be created, is WMP installed?")
   End
EndIf

Repeat
   ev = WaitWindowEvent()
   Select ev
      Case #PB_Event_Menu
         Select EventMenu()
            Case #MENU_ID_OPEN : fileOpen()
               
            Case #MENU_ID_UI_NONE, #MENU_ID_UI_MINI, #MENU_ID_UI_FULL : setUIMode(EventMenu())
               
            Case #MENU_ID_PLAY_PAUSE : playPause()
            
            Case #MENU_ID_STOP : stop()
         EndSelect
   EndSelect
Until  ev = #PB_Event_CloseWindow


Last edited by Justin on Tue Jun 23, 2020 10:53 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Windows Media Player Control
PostPosted: Sun Jun 21, 2020 12:11 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed May 27, 2020 12:26 pm
Posts: 128
I added a link to this subject in the french forum.


Top
 Profile  
Reply with quote  
 Post subject: Re: Windows Media Player Control
PostPosted: Tue Jun 23, 2020 9:29 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 2:49 pm
Posts: 679
Updated with event handling, it connects to the _WMPOCXEvents interface, you will need to refer to the documentation, see example.
Also download the updated WMPlayer.OCX.pbi.

There is a bug in PB wich produces an IMA when you call an interface method with a bstr param from inside a structure, i posted it more than one year ago i think. This is another example with the fix, it is marked in the test example.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye