3

I try to use Windows Media Player to play audio files via COM. The following code works fine in VBS:

Set wmp = CreateObject("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 50
wmp.URL = "C:\Windows\Media\tada.wav"
while wmp.Playstate <> 1
WSH.Sleep 100
wend

Unfortunately, the identical code doesn't play any sound in Python:

import win32com.client
import time

wmp = win32com.client.dynamic.Dispatch("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 50
wmp.URL = r"C:\Windows\Media\tada.wav"
while wmp.Playstate != 1:
    time.sleep(0.1)

COM interaction seems to work tough, as I can create new media objects and query info about them. It's just that no sound is ever audible.

>>> media = wmp.newMedia(r"C:\Windows\Media\tada.wav")
>>> media.durationString
'00:01'
>>> wmp.currentMedia = media
>>> wmp.play()                 # No sound audible.
>>> wmp.PlayState
9                              # wmppsTransitioning

PlayState is always reported to be wmppsTransitioning, no matter what I do.

The problem appears with Python2.7, 3.2 and 3.3 with the last two PyWin32 versions (218 and 219). OS is Windows 7 x64, the Python interpreters are all compiled for 32 bits. WMPlayer.OCX can be loaded successfully and COM works, so I don't think this is a 32bit/64bit DLL issue.

Any idea why it works with VBS and not with Python? How could I further debug this?

Christian Aichinger
  • 6,989
  • 4
  • 40
  • 60
  • Can you ensure your Python thread is in a single-threaded apartment (STA)? – acelent Aug 06 '14 at 22:59
  • Adding ``pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) `` at the beginning of the file doesn't help. Still the same result (silence/``wmppsTransitioning``). – Christian Aichinger Aug 07 '14 at 11:13
  • 1
    So it seems the problem is that `time.sleep` doesn't pump window messages. Use some other timeout function that pumps window messages. – acelent Aug 07 '14 at 12:14
  • Dumping ``win32gui.PumpWaitingMessages()`` into the loop solves the issue. If you turn your comment into an answer I'll gladly accept. – Christian Aichinger Aug 07 '14 at 15:16

1 Answers1

4

It seems the problem is that time.sleep doesn't pump window messages. Use some other timeout function that pumps window messages.

The reason is that Windows Media Player is an STA components, most probably because it's most commonly used as a graphical component. Some of its internals depend on regular message pumping, most probably a high-precision multimedia timer thread that sends window messages for communication, or it might depend on actual WM_TIMER messages.

acelent
  • 7,965
  • 21
  • 39
  • 1
    In fact, everything that internally invokes a Win32 message pump will do. ``PumpMessages``/``PumpWaitingMessages`` is one way. Just using WMP from the main thread of a wxPython/PyQt/PySide/... program works as well. – Christian Aichinger Aug 07 '14 at 17:02