使用 WinRT for python 进行事件处理

问题描述 投票:0回答:1

任务

我正在尝试制作一个工具,可以自动识别非 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)
python events windows-runtime python-asyncio winrt-async
1个回答
3
投票

首先,仅供参考,我在

https://github.com/pywinrt
上启动了 PyWinRT 和 winrt 包的社区分支,并在 PyPI 上发布了单独的命名空间包,例如 winrt.Windows.Media.Control 。其中包含对未维护的
winrt
包的许多修复,包括修复一些严重的问题,例如在
await
方法的每个
_async()
上泄漏 COM 对象。新软件包还包括类型提示,使解决此类问题变得更加容易。

事件处理程序的使用方式目前记录在here

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

import asyncio
import contextlib

from winrt.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:
                ...


async def main():
    async with contextlib.AsyncExitStack() as stack:
        loop = asyncio.get_running_loop()

        manager = await SessionManager.request_async()

        # by default, callbacks happen on a background thread, so we need
        # to use call_soon_threadsafe to run the update on the main thread
        def handle_sessions_changed(
            manager: SessionManager, args: SessionsChangedEventArgs
        ) -> None:
            loop.call_soon_threadsafe(update_sessions(manager))

        # add callback to handle any future changes
        sessions_changed_token = manager.add_sessions_changed(handle_sessions_changed)
        # ensure the callback is removed when the function exits
        stack.callback(manager.remove_sessions_changed, sessions_changed_token)

        # handle current state
        await update_sessions(manager)

        event = asyncio.Event()
        # wait forever - a real app would call event.set() to end the app
        await event.wait()


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

由于某种原因,该事件实际上似乎并未触发,但快速网络搜索表明这是

GlobalSystemMediaTransportControlsSessionManager.SesssionsChanged
的常见问题,并且似乎与 Python 绑定无关。

© www.soinside.com 2019 - 2024. All rights reserved.