pywinrt / python-winsdk

Python package with bindings for Windows SDK
https://python-winsdk.readthedocs.io
MIT License
77 stars 8 forks source link

IRandomAccessStreamReference.open_read_async() doesnt return #40

Closed a-usr closed 1 year ago

a-usr commented 1 year ago

As the title suggests, IRandomAccessStreamReference.open_read_async() takes forever to return. The IRandomAccessStreamReference was provided by winsdk.windows.media.control.GlobalSystemMediaTransportControlsSession.get_playback_info() (I am converting the output to a dictionary using the following function:

def props_to_dict(props):
    return {
        attr: props.__getattribute__(attr) for attr in dir(props) if attr[0] != '_'
    }

the StreamReference in question can be found under the 'thumbnail' key

dlech commented 1 year ago

Can you give a complete minimal reproducible test case?

a-usr commented 1 year ago

Alright... After completing the "reproducible" test case, i noticed that while in my program the function never ends, in the test program it does... I'll look further into this, but since it currently looks like the mistake is on my end I'll close this issue for now.

In case if youre interested, here is the test case anyways:

import asyncio
import PIL.Image as Image
import io
from winsdk.windows.media.control import GlobalSystemMediaTransportControlsSessionManager
from winsdk.windows.storage.streams import Buffer, InputStreamOptions, DataReader
import winsdk
THUMBNAIL_BUFFER_SIZE = 5 * 1024 * 1024
async def main():
    sessions = await GlobalSystemMediaTransportControlsSessionManager.request_async()
    playback_dict = await get_media_info(sessions.get_current_session())
    try:
        r_a_Stream_ref: winsdk.windows.storage.streams.IRandomAccessStreamReference
        r_a_Stream_ref = playback_dict["thumbnail"]
    except KeyError:
        print("Start some media (Something like youtube or spotify, it has to register with the OS)")
        return
    Async_operation = r_a_Stream_ref.open_read_async()
    while Async_operation.status == 0:
        # I Wouldve used Async_operation.completed != True, however this throws a NotImplementedException
        print(Async_operation.status) #this prints 0 indefinetly
    buffer = Buffer(THUMBNAIL_BUFFER_SIZE)
    readable_stream = Async_operation.get_results()
    await readable_stream.read_async(buffer, buffer.capacity, InputStreamOptions.READ_AHEAD)
    print(buffer)
    buffer_reader = DataReader.from_buffer(buffer)
    byte_arr = bytearray()
    for i in range(0, buffer.length):
        byte_arr.append(buffer_reader.read_byte())
    #print(byte_arr)
    img = Image.open(io.BytesIO(byte_arr))
    img.save(".\\thumbnail.png")

def props_to_dict(props):
    return {
        attr: props.__getattribute__(attr) for attr in dir(props) if attr[0] != '_'
    }
async def get_media_info(current_session):

    if current_session:
        media_props = await current_session.try_get_media_properties_async()
        return {
            song_attr: media_props.__getattribute__(song_attr)
            for song_attr in dir(media_props)
            if song_attr[0] != '_'
        }
if __name__ == "__main__":
    asyncio.run(main())
a-usr commented 1 year ago

btw, winsdk should be thread safe, right?

dlech commented 1 year ago

The Python wrappers are (because of the Python GIL). But the underlying Windows APIs are probably mostly not threadsafe.