3

I've been using the Status text of my MPC-HC window to determine if a video is playing or paused. However, when in Fullscreen mode or when the Status bar is hidden, the Status text does not update. Someone pointed out this bug to the MPC-HC team, but it hasn't been resolved: https://trac.mpc-hc.org/ticket/5640

I've tried using the MPC-HC API to get the state of the media player, but that required I run MPC-HC with the /slave command in order to trigger WM_COPYDATA, which I don't want.

More info on that method here:

media player classic - jump to point in video/audio programmatically

https://www.autoitscript.com/forum/topic/85354-media-player-classic-homecinema-mpc-remote-api-via-wm_copydata/

Here's the code I'm using right now. Fails if the Status bar is not visible.

IsMediaPlayerClassicPlaying() {

   ControlGetText, vPlayPause, Static3 , ahk_class MediaPlayerClassicW

   If InStr(vPlayPause, "Playing") 
       Return True
   Else
       Return False

}

I expected the function to return True whenever MPC is playing a video, but it only works if the status bar is visible. It seems that MPC doesn't update the status bar text (Playing/Paused) if it's not visible.

Kelly
  • 31
  • 3

2 Answers2

1

The only disadvantage of using the audio endpoint would be videos without sound. Not muted, without an audio track.

So, I can think of 2 other methods.

With MPC API: you don't need to run MPC with the /slave command line. Even if you are already running MPC it just needs to execute the Run command with the /slave switch to tell MPC that AHK is going to communicate with it.

Then the monitor will update a global variable every time the playback status changes. There's no way of directly querying the status, just change it.

To test this, open MPC and any video, then this AHK script. F1 will connect and F2 will give you the status. Caveat: after connecting the status isn't updated, only after the first status change the variable is meaningful.

global isMediaPlayerClassicPlaying := -1

OnMessage(WM_COPYDATA := 0x4A, "WM_COPYDATA")

; Connect MPC with AHK
F1::Run % "mpc-hc64.exe /slave " A_ScriptHwnd + 0, D:\Apps\Media Player Classic

F2::MsgBox % isMediaPlayerClassicPlaying

WM_COPYDATA(wParam, lParam)
{
    dwData := NumGet(lParam + 0)
    lpData := NumGet(lParam + A_PtrSize * 2)
    lpData := StrGet(lpData)
    if (dwData = 0x50000000) ; CMD_CONNECT := 0x50000000
    {
        WinGetClass vWinClass, % "ahk_id" lpData
        if (vWinClass = "MediaPlayerClassicW")
            OutputDebug MPC API on
    }
    if (dwData = 0x50000002) ; CMD_PLAYMODE := 0x50000002
        isMediaPlayerClassicPlaying := (lpData = 0)
    return true
}

The second option is the most solid but a little bit slow (takes around 1 second). In the options enable the web interface, then use this script:

F1::MsgBox % IsMediaPlayerClassicPlaying()
IsMediaPlayerClassicPlaying()
{
    url := "http://localhost:13579/variables.html"
    whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    whr.Open("GET", url, false)
    whr.Send()
    RegExMatch(whr.ResponseText, "(?<=state..)\d", state)
    return state = 2
}
0

If MPC is playing something with audio, you can query the state of its audio session.

/*
  IsMPCPlaying: Determines if MPC is playing audio.

    Requirements:
     - AutoHotkey v1.1
     - VA.ahk v2.3  https://autohotkey.com/board/topic/21984-/
     - Windows 7 or later, in theory (tested only on Windows 10)

  If MPC is using a non-default audio playback device, specify the
  device using one of the mechanisms described in the VA documentation.
  For example, "Speakers" or "playback:2".

  Returns 0 or 1 if an audio session is found, otherwise "".
*/
IsMPCPlaying(sound_device:="playback") {
    playing := ""
    dev := VA_GetDevice(sound_device)
    if VA_IMMDevice_Activate(dev, "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", 7, 0, sm := 0) = 0 {
        VA_IAudioSessionManager2_GetSessionEnumerator(sm, se := 0)
        VA_IAudioSessionEnumerator_GetCount(se, count := 0)
        Loop % count {
            VA_IAudioSessionEnumerator_GetSession(se, A_Index-1, sc)
            if sc2 := ComObjQuery(sc, "{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}") {
                VA_IAudioSessionControl2_GetProcessId(sc2, pid)
                if WinExist("ahk_class MediaPlayerClassicW ahk_pid " pid)
                    VA_IAudioSessionControl_GetState(sc2, playing)
                ObjRelease(sc2)
            }
            ObjRelease(sc)
        } until playing != ""
        ObjRelease(se)
        ObjRelease(sm)
    }
    ObjRelease(dev)
    return playing
}

If you're querying the status frequently, you could instead retrieve the audio session control (sc2) once and just call VA_IAudioSessionControl_GetState(sc2, state) as needed. I'm not sure what would happen after MPC terminates; I'd guess the VA functions would start returning failure (non-zero).

Another way is to query the state of the Play button:

SendMessage 0x40A, 887, 0, ToolbarWindow321, ahk_class MediaPlayerClassicW

However, this has the same issue as querying the status bar: the button isn't updated when it isn't visible. Side note: that's almost certainly by design - it is intended for display to the user, not for automation/other apps.

Lexikos
  • 987
  • 6
  • 16