queensoft

Embedded video WMPlayer Control - seek problem

10 posts in this topic

I need to play a video (this is working), display current position using slider (also working), but be able to seek video using same slider (this is the problem).

Just like any other video player, where you have a seek/position bar.

Everything is working like I want it, except the slider: display current position, but also seek when user changes slider position.

My code, so far, attached below. There are a few comments to help you along the way.

I also attached a short MP4 file, so you can test using exact same files.

#include <WinAPI.au3>
#include <APIConstants.au3>
#include <SliderConstants.au3>
#Include <GuiSlider.au3>

#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <IE.au3>


Global $iOld = 0, $iCur = 0

Global $width = 500
Global $height = 280
Global $IEControl; = null;
Global $MyGUI = GUICreate("WMPlayer Control", 800,600,-1,-1, $WS_OVERLAPPEDWINDOW)

; I need to dispalay on top / overlay some other controls
$b02 = GUICtrlCreateButton("BUTTON", 200, 10, 300, 40)
GuiCtrlSetState($b02, $GUI_ONTOP)


GUISwitch($MyGUI)
$h_cGUI = GUICreate("Embed Player", 780, 580, 10, 10, $WS_CHILD, "", $MyGUI )

Global $oIE = _GUICtrl_CreateWMPlayer("about:blank", 250, 0, $width, $height)
GuiCtrlSetState($oIE, $GUI_HIDE)

$slider01 = GUICtrlCreateSlider(10, 350, 780, 20)

$l01 = GUICtrlCreateLabel("Position: ", 10, 380, 100, 20)

GUISetState (@SW_SHOW, $MyGUI)
GUIRegisterMsg($WM_SIZE, "WM_SIZE")
GUISetState(@SW_SHOW, $h_cGUI)

Global $playerOBJ = _IEGetObjById($oIE, "objWMPlayer")
if NOT IsObj($playerOBJ) Then
    MsgBox(0, "Error", "WMP failed to be created.");
    Exit;
EndIf

$FileOpen = @ScriptDir & "\sample01.mp4"
If Not @error Then
    _wmpvalue($playerOBJ, "nocontrols")
    _wmploadmedia($playerOBJ,$FileOpen)
    ; allow some time to load video, will fix it later
    Sleep(222)
    $d = _wmpvalue($playerOBJ, "getduration")
    _wmpvalue($playerOBJ, "setposition", 0)
    GUICtrlSetLimit($slider01, $d, 0)
    GUICtrlSetData($slider01, 0)
Else
    Exit;
EndIf

While 1
    Sleep(50)
    $ps = _wmpvalue($playerOBJ, "playState")
    ; if video is playing
    if $ps=3 Then
        ; read video position, update slider and label
        $pos01 = _wmpvalue($playerOBJ, "getposition")
        GUICtrlSetData($slider01, $pos01)
        GUICtrlSetData($l01, Int($pos01))
    EndIf

    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

; >>>>>>>>>>>>>> THIS IS THE PROBLEM - update slider and, at the same time, user moves slider and video seeks accordingly
;~              $pos02 = GUICtrlRead($slider01)
;~              _wmpvalue($playerOBJ, "setposition", $pos02)
;~              _wmpvalue($playerOBJ, "play") ; not really necessary

WEnd

Func WM_SIZE($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam, $ilParam
    Local $xClient, $yClient
    $xClient = BitAND($ilParam, 0x0000FFFF)
    $yClient = BitShift($ilParam, 16)
    GUICtrlSetPos($IEControl, 0, 0, $xClient, $yClient)
    if NOT @error Then
        if IsObj($playerOBJ) Then $playerOBJ.width = $xClient;
        if IsObj($playerOBJ) Then $playerOBJ.height = $yClient;
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc

#cs
_wmploadmedia( $object, $URL )
$object:    Object returned from the $playerOBJ = _IEGetObjById($oIE, "objWMPlayer")
$URL:       Path or URL of the media
Return: None
#ce
Func _wmploadmedia( $object, $URL)
    $object.URL = $URL
    While Not $object.controls.isAvailable("play")
        Sleep(1)
    WEnd
    $object.controls.play()
EndFunc


; Function: _GUICtrl_CreateWMPlayer
; Purpose: Embed Windows Media Player and play one file or one playlist only.
; Notes: PARAM NAME="url" is ReadOnly
; Authors: squirrely1
; borderless IE embed example: GaryFrost
; Kudos - Kare Johansson, CFire
; References:
; http://msdn2.microsoft.com/en-us/library/ms930698.aspx
; http://www.w3schools.com/media/media_playerref.asp
; clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6 - wmplayer latest installed version
; clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95 - wmp 6.4
;===============================================
Func _GUICtrl_CreateWMPlayer($movieURL, $playerLeft, $playerTop, $playerWidth, $playerHeight, _
    $insetBorders = 0, $fullscreenMode = False, $showControls = True, $enableContextMenu = True, _
    $LoopMode = false, $playCount = 1, $playVolume = 100, $playBalance = 0, $enableFullScreenControls = True)

    If $fullscreenMode Then
        $fullscreenMode = "true"
    Else
        $fullscreenMode = "false"
    EndIf
    If $showControls Then
        $showControls = "true"
    Else
        $showControls = "false"
    EndIf
    If $enableContextMenu Then
        $enableContextMenu = "true"
    Else
        $enableContextMenu = "false"
    EndIf
    If $LoopMode Then
        $playCount = 999
    EndIf
    If $enableFullScreenControls Then
        $enableFullScreenControls = "true"
    Else
        $enableFullScreenControls = "false"
    EndIf

    Local $myIE_Obj = _IECreateEmbedded ()
    $IEControl = GUICtrlCreateObj($myIE_Obj, $playerLeft, $playerTop, $playerWidth, $playerHeight)
    GuiCtrlSetState($IEControl, $GUI_DISABLE )
    _IENavigate($myIE_Obj, "about:blank")
    Local $htmlWMP
    $htmlWMP = '' _
                & @CR & '<body style="margin:0;padding:0" >' _
                & @CR & '<OBJECT' _
                & @CR & 'ID="objWMPlayer"' _
                & @CR & 'STYLE="margin:0;padding:0"' _
                & @CR & 'HSPACE="0"' _
                & @CR & 'VSPACE="0"' _
                & @CR & 'BORDER="0"' _
                & @CR & 'WIDTH="' & $playerWidth & '"' _
                & @CR & 'HEIGHT="' & $playerHeight & '"' _
                & @CR & 'CLASSID="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6"' _
                & @CR & 'STANDBY="Loading Windows Media Player components..."' _
                & @CR & 'TYPE="application/x-ms-wmp">' _
                & @CR & '<PARAM NAME="allowHideControls" VALUE="true">' _
                & @CR & '<PARAM NAME="autoStart" VALUE="false">' _
                & @CR & '<PARAM NAME="audioStream" VALUE="false">' _
                & @CR & '<PARAM NAME="autoSize" VALUE="false">' _
                & @CR & '<PARAM NAME="balance" VALUE="' & $playBalance & '"><!-- -100 to 100 -->' _
                & @CR & '<!-- <PARAM NAME="bufferingTime" VALUE="5"><!-- seconds -->' _
                & @CR & '<PARAM NAME="clickToPlay" VALUE="false"><!-- has no effect -->' _
                & @CR & '<PARAM NAME="currentPosition" VALUE="0"><!-- start position within video, in seconds -->' _
                & @CR & '<PARAM NAME="enableContextMenu" VALUE="' & $enableContextMenu & '">' _
                & @CR & '<PARAM NAME="enableFullScreenControls" VALUE="' & $enableFullScreenControls & '">' _
                & @CR & '<PARAM NAME="enabled" VALUE="true"><!-- whether controls are enabled -->' _
                & @CR & '<PARAM NAME="fullScreen" VALUE="' & $fullscreenMode & '">' _
                & @CR & '<PARAM NAME="mute" VALUE="false">' _
                & @CR & '<PARAM NAME="playCount" VALUE="' & $playCount & '">' _
                & @CR & '<!-- <PARAM NAME="previewMode" VALUE="true"> -->' _
                & @CR & '<PARAM NAME="rate" VALUE="1"><!-- play speed of -.5 to 2 increments of .1 -->' _
                & @CR & '<PARAM NAME="sendPlayStateChangeEvents" VALUE="false">' _
                & @CR & '<PARAM NAME="showCaptioning" VALUE="false">' _
                & @CR & '<PARAM NAME="showControls" VALUE="' & $showControls & '">' _
                & @CR & '<PARAM NAME="showGotoBar" VALUE="false">' _
                & @CR & '<PARAM NAME="showPositionControls" VALUE="true"><!-- uiMode must = "full" -->' _
                & @CR & '<PARAM NAME="showStatusBar" VALUE="false"><!-- has no effect -->' _
                & @CR & '<PARAM NAME="showDisplay" VALUE="true"><!-- has no effect - reportedly shows filename -->' _
                & @CR & '<PARAM NAME="stretchToFit" VALUE="true">' _
                & @CR & '<PARAM NAME="uiMode" VALUE="full"><!-- invisible, none, mini, full -->' _
                & @CR & '<!-- <PARAM NAME="videoBorderWidth" VALUE="0"> -->' _
                & @CR & '<PARAM NAME="volume" VALUE="' & $playVolume & '"><!-- volume percent setting of wmplayer.exe -->' _
                & @CR & '<PARAM NAME="windowlessVideo" VALUE="false"><!-- must be the default (false) for function to work in wmp 9.0, otherwise might renders video directly in the client area -->' _
                & @CR & '</OBJECT>' _
                & @CR & '</body>'
    _IEDocWriteHTML ($myIE_Obj, $htmlWMP)
    _IEAction ($myIE_Obj, "refresh")
    $myIE_Obj.document.body.scroll = "no"
    $myIE_Obj.document.body.style.border = $insetBorders
    Return $myIE_Obj
EndFunc ;==>_GUICtrl_CreateWMPlayer

Func _wmpvalue( $object, $setting, $para=1 )
    Switch $setting
        Case "play"
            If $object.controls.isAvailable("play") Then $object.controls.play()
        case "stop"
            If $object.controls.isAvailable("stop") Then $object.controls.stop()
        case "pause"
            If $object.controls.isAvailable("pause") Then $object.controls.pause()
        case "invisible"
            $object.uiMode = "invisible"
        case "controls"
            $object.uiMode = "full"
        case "nocontrols"
            $object.uiMode = "none"
        case "fullscreen"
            $object.fullscreen = "True"
        Case "step"
            If $object.controls.isAvailable("step") Then Eval('object.controls.step($para)')
        Case "fastForward"
            If $object.controls.isAvailable("fastForward") Then $object.controls.fastForward()
        Case "fastReverse"
            If $object.controls.isAvailable("fastReverse") Then $object.controls.fastReverse()
        ; https://msdn.microsoft.com/en-us/library/windows/desktop/dd564085%28v=vs.85%29.aspx
        Case "playState"
            Return $object.playState
        Case "volume"
            $object.settings.volume = $para
        Case "rate"
            $object.settings.rate = $para
        Case "playcount"
            $object.settings.playCount = $para
        Case "setposition"
            $object.controls.currentPosition = $para
        Case "getposition"
            Return $object.controls.currentPosition
        Case "getpositionstring"
            Return $object.controls.currentPositionString
        Case "getduration"
            Return $object.currentMedia.duration
        Case "getname"
            Return $object.currentMedia.name
    EndSwitch
EndFunc

 

sample01.mp4

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Try with the following code

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>


    GUICreate("slider", 220, 100, 100, 200)


    Local $idSlider1 = GUICtrlCreateSlider(10, 10, 200, 20)
    $hSlider=GUICtrlGetHandle($idSlider1) ; get handle of slider
    GUICtrlSetLimit(-1, 200, 0) ; change min/max value

    GUISetState(@SW_SHOW)
    GUICtrlSetData($idSlider1, 45) ; set cursor

GUIRegisterMsg($WM_HSCROLL,"WM_HSCROLL")

Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)
    If $lParam=$hSlider Then
        $iPos=_WinAPI_HiWord($wParam)
        ConsoleWrite("pos:" & $iPos & @CRLF)
    EndIf
EndFunc

    L

You can find more info at Trackbar Notification Messages.

Edited by ahmet
Added missing function WM_HSCROLL
1 person likes this

Share this post


Link to post
Share on other sites

Almost perfect !!!

One small addition, if possible: it seems that the slider triggers the function continuously. When I click&drag the slider, the video is seeked continuously.

How to I make the video seek only when slider is released ?

I created a very simple function, I'm not really familiar with GUIRegisterMsg:

Func WM_HSCROLL($hWnd)
    $pos02 = GUICtrlRead($slider01)
    _wmpvalue($playerOBJ, "setposition", $pos02)
EndFunc

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

That is even simpler :D. There is no need to register messeage handler for WM_HSCROLL message.

Do
    $idMsg = GUIGetMsg()
    If $idMsg=$idSlider1 Then MsgBox(0,"Slider pos",GUICtrlRead($idSlider1))
Until $idMsg = $GUI_EVENT_CLOSE

I also noticed I did not post my function WM_HSCROLL :sweating:

Edited by ahmet

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

This isn't working, because the slider is already changed by the time the mouse is released.

$pos01 = _wmpvalue($playerOBJ, "getposition")
        GUICtrlSetData($slider01, $pos01)

The first idea is much much better.

I just need to update video position only once, when mouse button / slider is released.

Edited by queensoft

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

You can use flags

Global $ReasonForPosUpdate=0 ; 1 - update slider pos because of video playing
While 1
    Sleep(50)
    $ps = _wmpvalue($playerOBJ, "playState")
    $ReasonForUpdatePos=1 
    ; if video is playing
    if $ps=3 Then
        ; read video position, update slider and label
        $pos01 = _wmpvalue($playerOBJ, "getposition")
        GUICtrlSetData($slider01, $pos01)
        GUICtrlSetData($l01, Int($pos01))
    EndIf
    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $slider01
            If $ReasonForUpdate=0 Then
                _wmpvalue($playerOBJ, "setposition",GUICtrlRead($slider01))
            EndIf
            $ReasonForUpdate=0
    EndSwitch
    WEnd

Not tested :)

 

Edited by ahmet

Share this post


Link to post
Share on other sites

I have already found an alternate solution: I added 2 _IsPressed('01') checks.

If mouse button is NOT pressed, either:

- update the position from the video

- seek video when mouse is released.

If I get into trouble using this, I will take a look at your solution.

Thank you very much for your help.

Share this post


Link to post
Share on other sites

Here is a solution using GUIRegisterMsg()

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $TB_THUMBPOSITION=4

    GUICreate("slider", 220, 100, 100, 200)


    Local $idSlider1 = GUICtrlCreateSlider(10, 10, 200, 20)
    $hSlider=GUICtrlGetHandle($idSlider1) ; get handle of slider
    GUICtrlSetLimit(-1, 200, 0) ; change min/max value
    $idButton=GUICtrlCreateButton("Set",10,60)

    GUISetState(@SW_SHOW)
    GUICtrlSetData($idSlider1, 45) ; set cursor

GUIRegisterMsg($WM_HSCROLL,"WM_HSCROLL")


    Local $idMsg
    ; Loop until the user exits.
    Do
        $idMsg = GUIGetMsg()
        If $idMsg=$idButton Then GUICtrlSetData($idSlider1,45)
    Until $idMsg = $GUI_EVENT_CLOSE


Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)
    If $lParam=$hSlider Then
        $iPos=_WinAPI_HiWord($wParam)
        $iCode=_WinAPI_LoWord($wParam)
        If $iCode=$TB_THUMBPOSITION Then ConsoleWrite("pos:" & $iPos & @CRLF)
    EndIf
EndFunc

 

Share this post


Link to post
Share on other sites

Thanks, I will take a look tomorrow morning.

Share this post


Link to post
Share on other sites

You are welcome

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now