1 (изменено: Malcev, 2023-03-24 04:56:35)

Тема: AHK: Получение информации у медиа с WinRT API и MediaControl Class.

https://learn.microsoft.com/en-us/uwp/a … inrt-22621
Данный код получает название, артиста и hbitmap обложки проигрываемого медиа в фаерфоксе.
Но можно получать еще много чего, а также управлять медиа.
https://learn.microsoft.com/en-us/uwp/a … inrt-22621

app := "firefox.exe"
CreateClass("Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager", IGlobalSystemMediaTransportControlsSessionManagerStatics := "{2050c4ee-11a0-57de-aed7-c97c70338245}", GlobalSystemMediaTransportControlsSessionManagerStatics)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManagerStatics+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManagerStatics, "ptr*", GlobalSystemMediaTransportControlsSessionManager)   ; GlobalSystemMediaTransportControlsSessionManager.RequestAsync
WaitForAsync(GlobalSystemMediaTransportControlsSessionManager)
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0) ; sizeof(GdiplusStartupInput) = 16, 24
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken:=0, "ptr", &si, "ptr", 0)
return

f11::
title := artist := ""
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManager, "ptr*", GlobalSystemMediaTransportControlsSessionList)   ; GlobalSystemMediaTransportControlsSessionManager.GetSessions
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int*", count)   ; count
loop % count
{
   DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int", A_Index-1, "ptr*", GlobalSystemMediaTransportControlsSession)
   DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", SourceAppUserModelId)   ; GlobalSystemMediaTransportControlsSession.get_SourceAppUserModelId
   buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", SourceAppUserModelId, "uint*", length, "ptr")
   if (StrGet(buffer, "UTF-16") = app)
   {
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", GlobalSystemMediaTransportControlsSessionMediaProperties)   ; GlobalSystemMediaTransportControlsSession.TryGetMediaPropertiesAsync
      WaitForAsync(GlobalSystemMediaTransportControlsSessionMediaProperties)
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Title
      buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", length, "ptr")
      title := StrGet(buffer, "UTF-16")
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0)+9*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", hTitle)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Artist
      buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hTitle, "uint*", length, "ptr")
      artist := StrGet(buffer, "UTF-16")
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionMediaProperties+0)+15*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionMediaProperties, "ptr*", RandomAccessStreamReference)   ; GlobalSystemMediaTransportControlsSessionMediaProperties.get_Thumbnail
      if (DllCall(NumGet(NumGet(RandomAccessStreamReference+0)+6*A_PtrSize), "ptr", RandomAccessStreamReference, "ptr*", RandomAccessStreamWithContentType) = 0)   ; IRandomAccessStreamReference.OpenReadAsync
      {
         WaitForAsync(RandomAccessStreamWithContentType)
         VarSetCapacity(CLSID, 16, 0)
         DllCall("ole32\CLSIDFromString", "wstr", IID_IStream := "{0000000C-0000-0000-C000-000000000046}", "ptr", &CLSID)
         DllCall("ShCore\CreateStreamOverRandomAccessStream", "ptr", RandomAccessStreamWithContentType, "ptr", &CLSID, "ptr*", Stream, "uint")
         DllCall("gdiplus\GdipCreateBitmapFromStream", "ptr", Stream, "ptr*", pBitmap)
         DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
         DllCall("Gdiplus.dll\GdipDisposeImage", "ptr", pBitmap)
         ObjReleaseClose(Stream)
         ObjReleaseClose(RandomAccessStreamWithContentType)
      }
      ObjReleaseClose(RandomAccessStreamReference)
      ObjReleaseClose(GlobalSystemMediaTransportControlsSessionMediaProperties)
      ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
      break
   }
   ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
}
ObjReleaseClose(GlobalSystemMediaTransportControlsSessionList)
msgbox % "title: " title "`nartist: " artist "`nhbitmap: " hbitmap
if hbitmap
{
   DllCall("DeleteObject", "ptr", hBitmap)
   hBitmap := ""
}
return

CreateClass(string, interface := "", ByRef Class := "")
{
   CreateHString(string, hString)
   if (interface = "")
      result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
   else
   {
      VarSetCapacity(GUID, 16)
      DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
      result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   }
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object)
{
   AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
   loop
   {
      DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
      if (status != 0)
      {
         if (status != 1)
         {
            DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
            msgbox AsyncInfo status error: %ErrorCode%
            ExitApp
         }
         ObjRelease(AsyncInfo)
         break
      }
      sleep 10
   }
   DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
   ObjReleaseClose(Object)
   Object := ObjectResult
}

ObjReleaseClose(ByRef Object)
{
   if Object
   {
      if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"))
      {
         DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
         ObjRelease(Close)
      }
      ObjRelease(Object)
   }
   Object := ""
}

Пример отлова событий:

app := "firefox.exe"
GoSub init
return

Connected:
Disconnected:
Closed:
Opened:
Changing:
Stopped:
Playing:
Paused:
msgbox % a_thislabel
return

init:
#Persistent
OnExit, ExitSub
Events := [3 ;QueryInterface
          ,1 ;AddRef
          ,1 ;Release
          ,3] ;Invoke
VarSetCapacity(vtbl1, A_PtrSize*Events.MaxIndex(), 0)
For Index, ParameterCount In Events
   NumPut(RegisterCallback("PlaybackInfoChangedEvent", "Fast", ParameterCount, A_Index-1), vtbl1, A_PtrSize*(A_Index-1))
PlaybackInfoChangedEvent := DllCall("GlobalAlloc", "uint", 0, "ptr", A_PtrSize, "ptr")
NumPut(&vtbl1, PlaybackInfoChangedEvent+0, 0)

CreateClass("Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager", IGlobalSystemMediaTransportControlsSessionManagerStatics := "{2050c4ee-11a0-57de-aed7-c97c70338245}", GlobalSystemMediaTransportControlsSessionManagerStatics)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManagerStatics+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManagerStatics, "ptr*", GlobalSystemMediaTransportControlsSessionManager)   ; GlobalSystemMediaTransportControlsSessionManager.RequestAsync
WaitForAsync(GlobalSystemMediaTransportControlsSessionManager)
ObjReleaseClose(GlobalSystemMediaTransportControlsSessionManagerStatics)
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManager, "ptr*", GlobalSystemMediaTransportControlsSessionList)   ; GlobalSystemMediaTransportControlsSessionManager.GetSessions
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int*", count)   ; count
loop % count
{
   DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int", A_Index-1, "ptr*", GlobalSystemMediaTransportControlsSession)
   DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", SourceAppUserModelId)   ; GlobalSystemMediaTransportControlsSession.get_SourceAppUserModelId
   buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", SourceAppUserModelId, "uint*", length, "ptr")
   if (StrGet(buffer, "UTF-16") = app)
   {
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+27*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr", PlaybackInfoChangedEvent, "int64*", PlaybackInfoChangedEventToken)   ; GlobalSystemMediaTransportControlsSession.add_PlaybackInfoChanged
      GlobalSystemMediaTransportControlsSessionCurrent := GlobalSystemMediaTransportControlsSession
      SetTimer, Connected, -1
      break
   }
   ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
}
ObjReleaseClose(GlobalSystemMediaTransportControlsSessionList)

VarSetCapacity(vtbl2, A_PtrSize*Events.MaxIndex(), 0)
For Index, ParameterCount In Events
   NumPut(RegisterCallback("SessionsChangedEvent", "Fast", ParameterCount, A_Index-1), vtbl2, A_PtrSize*(A_Index-1))
SessionsChangedEvent := DllCall("GlobalAlloc", "uint", 0, "ptr", A_PtrSize*3+8+StrLen(app)+1, "ptr")
NumPut(&vtbl2, SessionsChangedEvent+0, 0)
NumPut(PlaybackInfoChangedEvent, SessionsChangedEvent+0, A_PtrSize)
NumPut(GlobalSystemMediaTransportControlsSessionCurrent, SessionsChangedEvent+0, A_PtrSize*2)
NumPut(PlaybackInfoChangedEventToken, SessionsChangedEvent+0, A_PtrSize*3, "int64")
StrPut(app, SessionsChangedEvent+A_PtrSize*3+8, "utf-8")
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0)+10*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionManager, "ptr", SessionsChangedEvent, "int64*", SessionsChangedEventToken)   ; GlobalSystemMediaTransportControlsSessionManager.add_SessionsChanged
return

ExitSub:
GlobalSystemMediaTransportControlsSessionCurrent := NumGet(SessionsChangedEvent+0, A_PtrSize*2)
PlaybackInfoChangedEventToken := NumGet(SessionsChangedEvent+0, A_PtrSize*3, "int64")
if GlobalSystemMediaTransportControlsSessionCurrent
{
   DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionCurrent+0)+28*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionCurrent, "int64", PlaybackInfoChangedEventToken)   ; GlobalSystemMediaTransportControlsSession.remove_PlaybackInfoChanged
   ObjReleaseClose(GlobalSystemMediaTransportControlsSessionCurrent)
}
DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionManager+0)+11*A_PtrSize), "int64", SessionsChangedEventToken)   ; GlobalSystemMediaTransportControlsSessionManager.remove_SessionsChanged
ObjReleaseClose(GlobalSystemMediaTransportControlsSessionManager)
DllCall("GlobalFree", "ptr", PlaybackInfoChangedEvent, "ptr")
DllCall("GlobalFree", "ptr", SessionsChangedEvent, "ptr")
ObjReleaseClose(PlaybackInfoChangedEvent)
ObjReleaseClose(SessionsChangedEvent)
ExitApp

PlaybackInfoChangedEvent(this, guid = "", ppvObject = "")
{
   static IID_IUnknown, p1, p2, oPlaybackStatus := {0:"Closed", 1:"Opened", 2:"Changing", 3:"Stopped", 4:"Playing", 5:"Paused"}
   if !IID_IUnknown
   {
      VarSetCapacity(p1, 16, 0)
      DllCall("ole32\CLSIDFromString", "wstr", IID_IUnknown := "{00000000-0000-0000-C000-000000000046}", "ptr", &p1)
      VarSetCapacity(p2, 16, 0)
      DllCall("ole32\CLSIDFromString", "wstr", IID_IPlaybackInfoChangedEvent := "{2bdf1426-d41f-5896-897f-efc0b0fa7392}", "ptr", &p2)
   }
   If (A_EventInfo = 0)
   {
      if DllCall("ole32\IsEqualGUID", "ptr", guid, "ptr", &p1) or DllCall("ole32\IsEqualGUID", "ptr", guid, "ptr", &p2)
      {
         NumPut(this, ppvObject+0)
         return 0
      }
      else
      {
         NumPut(0, ppvObject+0)
         return 0x80004002
      }
   }
   else if (A_EventInfo = 3)   ; Invoke
   {
      DllCall(NumGet(NumGet(guid+0)+9*A_PtrSize), "ptr", guid, "ptr*", GlobalSystemMediaTransportControlsSessionPlaybackInfo)   ; GlobalSystemMediaTransportControlsSession.GetPlaybackInfo
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionPlaybackInfo+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionPlaybackInfo, "int*", PlaybackStatus)   ; GlobalSystemMediaTransportControlsSessionPlaybackInfo.PlaybackStatus
      ObjReleaseClose(GlobalSystemMediaTransportControlsSessionPlaybackInfo)
      SetTimer, % oPlaybackStatus[PlaybackStatus], -1
      return 0
   }
   return 1
}

SessionsChangedEvent(this, guid = "", ppvObject = "")
{
   static IID_IUnknown, p1, p2, PlaybackInfoChangedEvent, GlobalSystemMediaTransportControlsSessionCurrent, PlaybackInfoChangedEventToken, app, oPlaybackStatus
   if !IID_IUnknown
   {
      VarSetCapacity(p1, 16, 0)
      DllCall("ole32\CLSIDFromString", "wstr", IID_IUnknown := "{00000000-0000-0000-C000-000000000046}", "ptr", &p1)
      VarSetCapacity(p2, 16, 0)
      DllCall("ole32\CLSIDFromString", "wstr", IID_ISessionsChangedEvent := "{2e2a8630-dc8c-530a-9746-bc984d4b029e}", "ptr", &p2)
      PlaybackInfoChangedEvent := NumGet(this+0, A_PtrSize)
      GlobalSystemMediaTransportControlsSessionCurrent := NumGet(this+0, A_PtrSize*2)
      PlaybackInfoChangedEventToken := NumGet(this+0, A_PtrSize*3, "int64")
      app := strget(this+A_PtrSize*3+8, "utf-8")
   }
   If (A_EventInfo = 0)
   {
      if DllCall("ole32\IsEqualGUID", "ptr", guid, "ptr", &p1) or DllCall("ole32\IsEqualGUID", "ptr", guid, "ptr", &p2)
      {
         NumPut(this, ppvObject+0)
         return 0
      }
      else
      {
         NumPut(0, ppvObject+0)
         return 0x80004002
      }
   }
   else if (A_EventInfo = 3)   ; Invoke
   {
      DllCall(NumGet(NumGet(guid+0)+7*A_PtrSize), "ptr", guid, "ptr*", GlobalSystemMediaTransportControlsSessionList)   ; GlobalSystemMediaTransportControlsSessionManager.GetSessions
      DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+7*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int*", count)   ; count
      loop % count
      {
         DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionList+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionList, "int", A_Index-1, "ptr*", GlobalSystemMediaTransportControlsSession)
         DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+6*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr*", SourceAppUserModelId)   ; GlobalSystemMediaTransportControlsSession.get_SourceAppUserModelId
         buffer := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", SourceAppUserModelId, "uint*", length, "ptr")
         if (StrGet(buffer, "UTF-16") = app)
         {
            SessionFound := 1
            if !GlobalSystemMediaTransportControlsSessionCurrent
            {
               DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSession+0)+27*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSession, "ptr", PlaybackInfoChangedEvent, "int64*", PlaybackInfoChangedEventToken)   ; GlobalSystemMediaTransportControlsSession.add_PlaybackInfoChanged
               GlobalSystemMediaTransportControlsSessionCurrent := GlobalSystemMediaTransportControlsSession
               NumPut(GlobalSystemMediaTransportControlsSessionCurrent, this+0, A_PtrSize*2)
               NumPut(PlaybackInfoChangedEventToken, this+0, A_PtrSize*3, "int64")
               SetTimer, Connected, -1
            }
            else
               ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
            break
         }
         ObjReleaseClose(GlobalSystemMediaTransportControlsSession)
      }
      if !SessionFound and GlobalSystemMediaTransportControlsSessionCurrent
      {
         DllCall(NumGet(NumGet(GlobalSystemMediaTransportControlsSessionCurrent+0)+28*A_PtrSize), "ptr", GlobalSystemMediaTransportControlsSessionCurrent, "int64", PlaybackInfoChangedEventToken)   ; GlobalSystemMediaTransportControlsSession.remove_PlaybackInfoChanged
         ObjReleaseClose(GlobalSystemMediaTransportControlsSessionCurrent)
         NumPut(0, this+0, A_PtrSize*2)
         NumPut(0, this+0, A_PtrSize*3, "int64")
         SetTimer, Disconnected, -1
      }
      ObjReleaseClose(GlobalSystemMediaTransportControlsSessionList)
      return 0
   }
   return 1
}


CreateClass(string, interface := "", ByRef Class := "")
{
   CreateHString(string, hString)
   if (interface = "")
      result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
   else
   {
      VarSetCapacity(GUID, 16)
      DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
      result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   }
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object)
{
   AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
   loop
   {
      DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
      if (status != 0)
      {
         if (status != 1)
         {
            DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
            msgbox AsyncInfo status error: %ErrorCode%
            ExitApp
         }
         ObjRelease(AsyncInfo)
         break
      }
      sleep 10
   }
   DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
   ObjReleaseClose(Object)
   Object := ObjectResult
}

ObjReleaseClose(ByRef Object)
{
   if Object
   {
      if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"))
      {
         DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
         ObjRelease(Close)
      }
      hr := ObjRelease(Object)
   }
   Object := ""
   return hr
}

Тема для обсуждения

2

Re: AHK: Получение информации у медиа с WinRT API и MediaControl Class.

Добавил пример отлова событий.