Windows Media Player Control

Share your advanced PureBasic knowledge/code with the community.
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Windows Media Player Control

Post by Justin »

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 files:
WMPlayer.OCX.pbi : The interface definitions, big file 104Kb.
wmp.pb : Small include of helper functions.
wmpTest.pb : A small working player.
captions.pb : Closed captions example using webgadget
ccsample.smi : Closed captions sample

I did not write any interface method wrapper, you will need to refer to the documentation:
https://docs.microsoft.com/en-us/window ... ence-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.

UPDATE:
04/23 Added closed captions example

wmp.pb helper:

Code: Select all

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: pointer to WMP_OBJECT.
;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
		*this\refCount = *this\refCount + 1
		
		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

Procedure wmp_GetUnknown(wmpid.i)
	Protected.IUnknown unk
	
	If AtlAxGetControl_(GadgetID(wmpid), @unk) = #S_OK
		ProcedureReturn unk
	EndIf 
EndProcedure

Procedure wmp_GetInterface(wmpid.i, *iid.IID)
	Protected.IUnknown unk
	Protected.i ifce
	
	If AtlAxGetControl_(GadgetID(wmpid), @unk) = #S_OK
		unk\QueryInterface(*iid, @ifce)
		unk\Release()
	EndIf 
	
	ProcedureReturn ifce
EndProcedure
wmpTest.pb example

Code: Select all

;Windows Media Player Example
;Justin 06/2020

XIncludeFile "wmp.pb"

EnableExplicit

Define.i ev
Global.i g_wmp, g_lastUIMode

;- Enum MENU_ID
Enumeration
	#MENU_ID_OPEN
	#MENU_ID_UI_NONE
	#MENU_ID_UI_MINI
	#MENU_ID_UI_FULL
	#MENU_ID_PLAY_PAUSE
	#MENU_ID_STOP
	#MENU_ID_GET_CURRENT_TIME
	#MENU_ID_FORWARD
	#MENU_ID_INCREASE_SPEED
	#MENU_ID_DECREASE_SPEED
	#MENU_ID_RESET_SPEED
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

Procedure getCurrentTime()
	Protected.IWMPControls controls
	Protected.d dPosition
	Protected.i bPosition
	
	controls = wmp_GetControls(g_wmp)
	If controls
		If controls\get_currentPosition(@dPosition) = #S_OK
			Debug dPosition
		EndIf 
		
		If controls\get_currentPositionString(@bPosition) = #S_OK
			Debug PeekS(bPosition)
			
			SysFreeString_(bPosition)
		EndIf
		
		Debug controls\put_currentPosition(dPosition + 10)
	EndIf 
EndProcedure

;Advances 10 seconds
Procedure forward()
	Protected.IWMPControls controls
	Protected.d currPos, inCrement

	inCrement = 10
	controls = wmp_GetControls(g_wmp)
	If controls
		controls\get_currentPosition(@currPos)
		controls\put_currentPosition(currPos + inCrement)
	EndIf 
EndProcedure

Procedure increaseSpeed()
	Protected.IWMPSettings sett
	Protected.d rate, incStep
	
	incStep = 0.1
	If g_wmp
		sett = wmp_GetInterface(g_wmp, ?IID_IWMPSettings)
		If sett
			sett\get_rate(@rate)
			sett\put_rate(rate + incStep)
			sett\Release()
		EndIf
	EndIf 
EndProcedure

Procedure decreaseSpeed()
	Protected.IWMPSettings sett
	Protected.d rate, incStep
	
	incStep = 0.1
	If g_wmp
		sett = wmp_GetInterface(g_wmp, ?IID_IWMPSettings)
		If sett
			sett\get_rate(@rate)
			sett\put_rate(rate - incStep)
			sett\Release()
		EndIf
	EndIf 
EndProcedure

Procedure resetSpeed()
	Protected.IWMPSettings sett
	
	If g_wmp
		sett = wmp_GetInterface(g_wmp, ?IID_IWMPSettings)
		If sett
			sett\put_rate(1.0)
			sett\Release()
		EndIf
	EndIf 
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")
MenuItem(#MENU_ID_GET_CURRENT_TIME, "Get current time")
MenuItem(#MENU_ID_FORWARD, "Forward")

MenuTitle("View")
OpenSubMenu("UI Mode")
MenuItem(#MENU_ID_UI_NONE, "None")
MenuItem(#MENU_ID_UI_MINI, "Mini")
MenuItem(#MENU_ID_UI_FULL, "Full")
CloseSubMenu()

MenuTitle("Speed")
MenuItem(#MENU_ID_INCREASE_SPEED, "Increase")
MenuItem(#MENU_ID_DECREASE_SPEED, "Decrease")
MenuItem(#MENU_ID_RESET_SPEED, "Reset")
CloseSubMenu()

AddKeyboardShortcut(0, #PB_Shortcut_Up, #MENU_ID_INCREASE_SPEED)
AddKeyboardShortcut(0, #PB_Shortcut_Down, #MENU_ID_DECREASE_SPEED)

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 

setUIMode(#MENU_ID_UI_NONE)

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()
				
				Case #MENU_ID_GET_CURRENT_TIME : getCurrentTime()
			
				Case #MENU_ID_FORWARD : forward()
				
				Case #MENU_ID_INCREASE_SPEED : increaseSpeed()
				
				Case #MENU_ID_DECREASE_SPEED : decreaseSpeed()
				
				Case #MENU_ID_RESET_SPEED : resetSpeed()

			EndSelect
	EndSelect
Until  ev = #PB_Event_CloseWindow
;captions.pb example using webgadget
;First load a caption file then load a movie

Code: Select all

;captions.pb

;Closed captions example.
;First load a closed captions file .smi, .sami, then load a movie.
;Justin 04/23

EnableExplicit

XIncludeFile "WMPlayer.OCX.pbi"

;- _APP
Structure _APP
	win.i
	webView.i ;WebGadget
	wb2.IWebBrowser2
	menu.i
EndStructure
Global._APP app

;- DATA
DataSection
;"{3050f485-98b5-11cf-bb82-00aa00bdce0b}"
	IID_IHTMLDocument3:
	Data.l $3050f485
	Data.w $98b5, $11cf
	Data.b $bb, $82, $00, $aa, $00, $bd, $ce, $0b
EndDataSection

#PLAYER_ID = "player"
#CAPTIONS_ID = "captions"

;- HTML
#HTML = "<html><head>" +
"<style>" +
	"body {" +
		"padding: 0 0 0 0;" +
		"margin: 0 0 0 0;" +
	"}" +
	"" +
	"#" + #PLAYER_ID + "{" +
		"width: 100%;" +
		"height: 100%;" +
		"margin: 0 0 0 0;" +
	"}" + 
	"" +
	"#" + #CAPTIONS_ID + "{" +
		"position: fixed;" +
		"left: 50%;" +
		"transform: translateX(-50%);" +
		"bottom: 0px;" +
	"}" + 
"</style></head>" +
"<body>" + 
~"<OBJECT ID=\"" + #PLAYER_ID + ~"\" CLASSID=\"clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6\">" +
		~"<param name=\"UIMode\" value=\"none\">" +
		~"<param name=\"autoStart\" value=\"true\">" +
		~"<param name=\"stretchToFit\" value=\"true\">" +
		~"<param name=\"windowlessVideo\" value=\"true\">" +
	"</OBJECT>" +
	~"<div id=\"" + #CAPTIONS_ID + ~"\"></div>" +
"</body>" + "</html>"

;- Enum CMD
Enumeration
	#CMD_OPEN
	#CMD_SET_CAPTION
EndEnumeration

Procedure win_on_size()
	ResizeGadget(app\webView, 0, 0, WindowWidth(app\win), WindowHeight(app\win) - MenuHeight())
EndProcedure

;Gets IWebBrowser2 from WebGadget
Procedure webView_getWebBrowser(webView.i)
	ProcedureReturn GetWindowLongPtr_(GadgetID(app\webView), #GWLP_USERDATA)
EndProcedure

;Gets IHTMLDocument3 from IWebBrowser2
Procedure webBrowser_getDocument3(wb.IWebBrowser2)
	Protected.IDispatch docDisp
	Protected.IHTMLDocument3 doc3
	Protected.l hr
	
	If wb = 0 : ProcedureReturn 0 : EndIf 
	
	;Get document IDispatch
	hr = wb\get_Document(@docDisp)
	If hr <> #S_OK : ProcedureReturn 0 : EndIf
	
	;Get IHTMLDocument3
	hr = docDisp\QueryInterface(?IID_IHTMLDocument3, @doc3)
	If hr <> #S_OK : ProcedureReturn 0 : EndIf
	docDisp\Release()
	
	ProcedureReturn doc3
EndProcedure

;Gets IWMPPlayer from IWebBrowser2
Procedure webBrowser_getPlayer(wb.IWebBrowser2)
	Protected.IHTMLDocument3 doc3
	Protected.IHTMLElement el
	Protected.IWMPPlayer player
	Protected.l hr
	
	If wb = 0 : ProcedureReturn 0 : EndIf 
	
	doc3 = webBrowser_getDocument3(wb)
	If doc3 = 0 : ProcedureReturn 0 : EndIf 
	
	hr = doc3\getElementById(#PLAYER_ID, @el)
	If hr <> #S_OK : Goto cleanup : EndIf
	
	hr = el\QueryInterface(?IID_IWMPPlayer, @player)
	If hr <> #S_OK : Goto cleanup : EndIf
	
	cleanup:
	If doc3 : doc3\Release() : EndIf
	If el : el\Release() : EndIf 
	
	ProcedureReturn player
EndProcedure

Procedure cmd_open()
	Protected.s file
	Protected.IWMPPlayer player
	
	player = webBrowser_getPlayer(app\wb2)
	If player = 0
		Debug "Error failed to get player"
		ProcedureReturn 0
	EndIf
	
	file = OpenFileRequester("Choose video", "", "", 0)
	If file
		player\put_URL(file)
	EndIf 
	
	cleanup:
	If player : player\Release() : EndIf
EndProcedure

Procedure cmd_setCaption()
	Protected.s captionFile
	Protected.IWMPPlayer player
	Protected.IWMPClosedCaption cc
	Protected.l hr
	
	player = webBrowser_getPlayer(app\wb2)
	If player = 0
		Debug "Error failed to get player"
		ProcedureReturn 0
	EndIf
	
	hr = player\get_closedCaption(@cc)
	If hr <> #S_OK : Goto cleanup : EndIf 
	
	captionFile = OpenFileRequester("Choose caption", "", "Captions file | *smi;*.sami | All files | *.*", 0)
	If captionFile
		cc\put_captioningId(#CAPTIONS_ID)
		cc\put_SAMIFileName(captionFile)
	EndIf
	
	cleanup:
	If player : player\Release() : EndIf
	If cc : cc\Release() : EndIf
EndProcedure

Procedure main()
	Protected.l ev, ww, wh
	Protected.b quit
		
	ww = 600
	wh = 400
	app\win = OpenWindow(#PB_Any, 10, 10, ww, wh, "WMP Captions", #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget)
	SmartWindowRefresh(app\win, #True)
	
	app\menu = CreateMenu(#PB_Any, WindowID(app\win))
	MenuTitle("File")
	MenuItem(#CMD_OPEN, "Open")
	MenuTitle("Captions")
	MenuItem(#CMD_SET_CAPTION, "Set caption")

	app\webView = WebGadget(#PB_Any, 0, 0, ww, wh, "")
	
	app\wb2 = webView_getWebBrowser(app\webView)
	If app\wb2 = 0
		Debug "Error failed to get webbrowser"
		End
	EndIf 
		
	SetGadgetItemText(app\webView, #PB_Web_HtmlCode, #HTML)
		
	BindEvent(#PB_Event_SizeWindow, @win_on_size(), app\win)
	
	HideWindow(app\win, #False)

	quit = #False
	Repeat
		ev = WaitWindowEvent()
		Select ev
			Case #PB_Event_Menu
				Select EventMenu()
					Case #CMD_OPEN : cmd_open()
					Case #CMD_SET_CAPTION : cmd_setCaption()
				EndSelect
				
			Case #PB_Event_CloseWindow
				quit = #True
		EndSelect
	Until quit
EndProcedure

main()
;ccsample.smi closed captions file sample, proportional font size

Code: Select all

<SAMI>
<HEAD>
    <Title>Close Captioning Sample</Title>

    <STYLE TYPE="text/css">
        <!--
            P {margin-top:3pt; margin-left:5pt; font-size: 4vh;
               font-family: tahoma, sans-serif; font-weight: normal;
               color: white;}
            .ENUSCC {Name:'English Captions'; lang: en-US; SAMIType:CC;}
        -->
    </Style>
</HEAD>

<BODY>
	<SYNC Start=1000>
		<P Class=ENUSCC>Great reason to visit Seattle, brought to you by two out-of-staters.
	<SYNC Start=4000>
		<P Class=ENUSCC>So you know, there's lots of great reasons to come visit Seattle.
	<SYNC Start=7000>
		<P Class=ENUSCC>That's right, I came here because of the coffee.
	<SYNC Start=9000>
		<P Class=ENUSCC>Yah, everyone knows the coffee.
	<SYNC Start=12000>
		<P Class=ENUSCC>And I heard about the drivers.
	<SYNC Start=14000>
		<P Class=ENUSCC>Well, you know, but then it rains...and it's bad, it's bad.
	<SYNC Start=19000>
		<P Class=ENUSCC>But the traffic in general is...
	<SYNC Start=21000>
		<P Class=ENUSCC>Terrible.
	<SYNC Start=23000>
		<P Class=ENUSCC>OK, yah, yah.  But, the weather!
	<SYNC Start=26500>
		<P Class=ENUSCC>It doesn't rain all the time...yes, it does.
	<SYNC Start=30000>
		<P Class=ENUSCC>Yah.  Nevermind.
    <SYNC Start=34000>
        <P Class=ENUSCC>End of Stream.
</BODY>
</SAMI>
Last edited by Justin on Sun Apr 23, 2023 12:44 pm, edited 10 times in total.
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Windows Media Player Control

Post by Olli »

Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

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.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Windows Media Player Control

Post by jak64 »

Hello,
I am French and don't speak English very well.
Thanks for the code but is there a command to adjust the video playback speed (to play in slow motion or fast motion)?
thank you
User avatar
mk-soft
Always Here
Always Here
Posts: 5333
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Windows Media Player Control

Post by mk-soft »

Haven't tested the code.
But if the parameter should be a BSTR, you have to pass a BSTR too.

Code: Select all

Procedure fileOpen()
   Protected.s file, *bstrFile
   Protected.IWMPCore core = wmp_GetCore(g_wmp)
   Protected.WMP_OBJECT *wmp = wmp_GetObject(g_wmp)
   
   file = OpenFileRequester("Open", "", "", 0)
   If file
     *bstrFile = SysAllocString_(file)
     core\put_URL(*bstrFile) 
      SysFreeString_(*bstrFile)
;----------------- PB BUG ------------------------
;Calling a method with a bstr from inside a structure produces an IMA.
;*wmp\wmpCore\put_URL(file) ;   IMA
;-------------------------------------------------
   EndIf
EndProcedure
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

Hi jak i updated the code in wmp.pb with a new function and an important bug fix, you can set the playback speed with this method:
https://docs.microsoft.com/en-us/previo ... s-put_rate

Like this:

Code: Select all

;Play at 0.5 speed
Define.IWMPSettings sett

sett = wmp_GetInterface(g_wmp, ?IID_IWMPSettings)
If sett
	sett\put_rate(0.5)
	sett\Release()
EndIf 
hi mksoft, the bstr thing it's a pb bug check it. it only happens when you call a method containing a bstr through a structure, and that method is declared with a p-bstr, calling outside the structure works.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Windows Media Player Control

Post by jak64 »

Hi,

Thanks for the code but I don't know where in the wmp.pb program code I should add these lines. ?
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

Anywhere after the control has been created
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Windows Media Player Control

Post by jak64 »

hi,

I'm sorry, but I don't understand.
I added the lines of code in the wmp.pb program and I have a syntax error ...

Code: Select all

Procedure wmp_GetInterface(wmpid.i, *iid.IID)
   Protected.IUnknown unk
   Protected.i ifce
   
   If AtlAxGetControl_(GadgetID(wmpid), @unk) = #S_OK
      unk\QueryInterface(*iid, @ifce)
      unk\Release()
   EndIf
   ProcedureReturn ifce
   
   ;Play at 0.5 speed
Define.IWMPSettings sett

sett = wmp_GetInterface(g_wmp, ?IID_IWMPSettings)
If sett
   sett\put_rate(0.5)
   sett\Release()
EndIf
EndProcedure
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

I updated the wmpTest.pb in my very first post, i put the code just before the event loop but you can put it anywhere once you have the control id returned by wmp_Create().
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

I was wrong, you have to use that code once a movie has been loaded, i updated the wmpTest.pb file again, the code is in the fileOpen() procedure.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Windows Media Player Control

Post by jak64 »

Hi,
Thank you, it's ok but...

I would like to display the video (for a game) but without any interface, only the video. The speed of the video would be adjusted with the up and down arrow keys on the keyboard. Is it possible ?
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Windows Media Player Control

Post by Olli »

@jak65

It seems that in your sentence << It's ok >>, this means

<< my technical wish is now added, knowing I wanted to change the speed of a movie. >>

If some details miss, we can imagine, you are again searching how to change speed...



Now, for a second wish, as to change the movie support, you have to test several handles.

I cannot test it. But I am sure searching the expression GADGETID will go to this

Code: Select all

If AtlAxCreateControl_("WMPlayer.OCX", GadgetID(*wmp\container), #Null, #Null) = #S_OK
I suppose WindowId can provide a right handle, replacing GadgetId with WindowId.

And maybe (I insist "maybe") an other handle type could be tested, as MaterialId in a 3D render. But it is purely fictive without test.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Windows Media Player Control

Post by jak64 »

Hi
This is my code

Code: Select all

If InitMovie() = 0
  MessageRequester("Erreur", "Pb avec InitMovie !", 0)
  End
EndIf
If InitKeyboard()=0
    MessageRequester("Erreur", "Pb avec InitKeyboard !", 0)
  End
EndIf 
If InitSprite()=0
    MessageRequester("Erreur", "Pb avec InitSprite !", 0)
  End
EndIf 

nom_video$ = "D:\Purebasic\Lecteur vidéo\2 fast 2 furious (2003).avi"
If nom_video$
  If LoadMovie(0,nom_video$)
    If OpenWindow(0, 100, 150, MovieWidth(0), MovieHeight(0), "PureBasic - Movie", #PB_Window_BorderLess)=0
      MessageRequester("erreur","Pb fenêtre")
      End
    EndIf
    If OpenWindowedScreen(WindowID(0),100,150,MovieWidth(0), MovieHeight(0))=0
      MessageRequester("erreur","fenêtre screen")
      End
    EndIf
    
    PlayMovie(0, WindowID(0))
    Repeat
      ExamineKeyboard()
    Until WaitWindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
  Else
    MessageRequester("Erreurr", "Pb avec lecture de la vidéo...", 0)
  EndIf
EndIf
I would just like to change the speed of the video with the arrows on the keyboard:
Up arrow: speed up the video
Down arrow: slow down the video

I want there to be only the video displayed (without any button ... play, pause, nothing).

Can you help me please ?
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Windows Media Player Control

Post by Justin »

hi jak i update again wmpTest.pb in my first post, now it does that. with arrow keys or the menu.
Post Reply