python - 使用 WinRT for python 进行事件处理

标签 python events windows-runtime python-asyncio winrt-async

任务

我正在尝试制作一个工具,可以自动识别非 Spotify 源的播放,并在其他音频播放期间暂停 Spotify。我一直在使用 Microsoft 的 Python WinRT 投影 ( https://github.com/Microsoft/xlang/tree/master/src/package/pywinrt/projection )。我可以让程序识别音频源和播放状态,但只能从调用该函数的那一刻开始。之后就停止更新。

问题

我的主要问题是理解 WinRT 如何在 Python 中实现事件处理。 Windows 文档讨论了“更改的播放事件”( https://learn.microsoft.com/en-us/uwp/api/windows.media.control.globalsystemmediatransportcontrolssession.playbackinfochanged?view=winrt-22000 ),但我找不到任何关于如何在 API 的 Python 投影中完成此操作的线索。

当前状态

这是到目前为止我的代码,感谢任何帮助。

import asyncio
import time
from winrt.windows.media.control import \
    GlobalSystemMediaTransportControlsSessionManager as MediaManager
from winrt.windows.media.control import \
    GlobalSystemMediaTransportControlsSession as SessionMananger
from winrt.windows.media.control import \
    PlaybackInfoChangedEventArgs as PlaybackEventArgs

async def toggle_spotify():
    sessions = await MediaManager.request_async() #grab session manager instance

    all_sessions = sessions.get_sessions() #grab sequence of current instances
    for current_session in all_sessions: #iterate and grab desired instances
        if "chrome" in current_session.source_app_user_model_id.lower():
            chrome_info = current_session.get_playback_info()
        if "spotify" in current_session.source_app_user_model_id.lower():
            spotify_manager = current_session 
            spotify_info = current_session.get_playback_info()
    if chrome_info.playback_status == 4 and spotify_info.playback_status == 4: #status of 4 is playing, 5 is paused
        await spotify_manager.try_toggle_play_pause_async()
    elif chrome_info.playback_status == 5 and spotify_info.playback_status == 5:
        await spotify_manager.try_toggle_play_pause_async()
        # print(f"chrome playback status: {chrome_info.playback_status}")
        # print(f"chrome playback status: {spotify_info.playback_status}")
        # print("+++++++++++++++++")
        # time.sleep(2)

if __name__ == '__main__':
    #asyncio.run(get_media_info())
    while True: #mimicking event handling by looping
        asyncio.run(toggle_spotify())
        time.sleep(0.1)

最佳答案

首先,仅供引用,我已经启动了 PyWinRT 和 winrt 的社区分支。包裹在https://github.com/pywinrt并发表了winsdk PyPI 上的包。这包含对看似未维护的许多修复 winrt包,包括修复一些严重的问题,例如在每个 await 上泄漏 COM 对象的_async()方法。新winsdk包还包含类型提示,使解决此类问题变得更加容易。

当前记录了事件处理程序的使用方式 here .

因此,对于这种特定情况,您的代码可能如下所示:

import asyncio

from winsdk.windows.media.control import (
    GlobalSystemMediaTransportControlsSessionManager as SessionManager,
    GlobalSystemMediaTransportControlsSessionPlaybackStatus as PlaybackStatus,
    SessionsChangedEventArgs,
)


async def update_sessions(manager: SessionManager) -> None:
    for session in manager.get_sessions():
        if "chrome" in session.source_app_user_model_id.lower():
            chrome_info = session.get_playback_info()
            if chrome_info.playback_status == PlaybackStatus.PLAYING:
                ...


def handle_sessions_changed(manager: SessionManager, args: SessionsChangedEventArgs) -> None:
    asyncio.create_task(update_sessions(manager))


async def main():
    manager = await SessionManager.request_async()

    # add callback to handle any future changes
    sessions_changed_token = manager.add_sessions_changed(handle_sessions_changed)

    try:
        # handle current state
        asyncio.create_task(update_sessions(manager))

        event = asyncio.Event()
        # wait forever - a real app would call event.set() to end the app
        await event.wait()
    finally:
        # remove the callback
        manager.remove_sessions_changed(sessions_changed_token)


if __name__ == '__main__':
    asyncio.run(main())

出于某种原因,该事件实际上似乎并未触发,但快速网络搜索表明这是 GlobalSystemMediaTransportControlsSessionManager.SesssionsChanged 的常见问题。并且似乎与 Python 绑定(bind)无关。

另请注意 asyncio.create_task()仅当 update_sessions() 时才需要实际上是在等待一些东西,否则可以直接调用。

关于python - 使用 WinRT for python 进行事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71005262/

相关文章:

c# - 如何在 WinRT 中同时允许多个弹出窗口?

python - 从xml中提取元素

java - 不作弊地实现虚拟线程

python - 命令不同步你现在不能运行这个命令

javascript - 编写一个定期调用的滚动回调

c# - 将 Async Task 与 Dispatcher 结合使用以从 ViewModel 循环更新 WP8.1 WinRT 的 UI 线程

python - 如何在Python中删除文件中的重复行

java - 如何根据保存在数据库android中的日期和时间设置闹钟

java - Java 中有面板监听器吗?

C++/CX 工厂类提供具有相同数量参数的重载构造函数