Windows Media Player Control
Posted: Sat Jun 20, 2020 4:28 pm
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:
wmpTest.pb example
;captions.pb example using webgadget
;First load a caption file then load a movie
;ccsample.smi closed captions file sample, proportional font size
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
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
;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()
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>