MediaCtrl mystery

In the attached little demonstration program, MediaCtrl plays a music file when the player is created in the frame init but not when it’s created by a function. I don’t understand why it works one way but not the other; I’d be grateful if someone could explain it.

Patrick

playtest.py (721 Bytes)

Patrick Maher wrote:

In the attached little demonstration program, MediaCtrl plays a music
file when the player is created in the frame __init__ but not when
it's created by a function. I don't understand why it works one way
but not the other; I'd be grateful if someone could explain it.

wx.MediaCtrl is an asynchronous control. It loads the media in a
separate thread. The file has not yet been loaded by the time you call
Play. The solution is to catch the EVT_MEDIA_LOADED event, and do the
playing there:

    def play(self,event):
        self.player=wx.media.MediaCtrl(self.panel, -1, fn)
        self.player.Bind(wx.media.EVT_MEDIA_LOADED,self.play1)
    def play1(self,event):
        self.player.Play()

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Tim, thank you for your response. I tried the code you suggested (modified file attached) but, unfortunately, it didn’t work for me—the file still doesn’t play. I also tried a few other ways of ensuring that the media loaded before player.Play() was invoked but they didn’t work either. So I still don’t understand what’s going wrong. The fact that there is no error message makes it harder to understand.

Patrick

playtest2.py (684 Bytes)

On further investigation, I found that the reason Tim’s code doesn’t work (on my computer, anyway) is that EVT_MEDIA_LOADED is never generated and so the play1 function is never activated. But I also found that Tim’s diagnosis of the source of the problem is correct: Play is called too soon when the command comes right after Load. So I’m now looking for a way to get the needed delay before calling play and would welcome suggestions.

Patrick

You can try this:
    def play(self,event):
        self.player=wx.media.MediaCtrl(self.panel, -1, "Ironic.wma")
        wx.CallLater(1000, self.play1)
    def play1(self,event=None):
        self.player.Play()

This works for me on Windows. But you have a one second delay.

I saw this in the demo:
def __init__(self, ...):
   ...
   self.mc = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER)
   ...
   self.Bind(wx.media.EVT_MEDIA_LOADED, self.OnMediaLoaded)
   ...
   #self.DoLoadFile(os.path.abspath("data/testmovie.mpg"))
   wx.CallAfter(self.DoLoadFile, os.path.abspath("data/
testmovie.mpg"))
   ...

def DoLoadFile(self, path):
        ...
        if not self.mc.Load(path):
            wx.MessageBox("Unable to load %s: Unsupported format?" %
path,
                          "ERROR",
                          wx.ICON_ERROR | wx.OK)
        else:
            ...

def OnMediaLoaded(self, evt):
   ...

That's straight from the demo, you can try to put the CallAfter part
inside the button handler. (weird, but the code as is didn't work...)

···

On Dec 31, 6:17 pm, Patrick Maher <patr...@maher1.net> wrote:

On further investigation, I found that the reason Tim's code doesn't work
(on my computer, anyway) is that EVT_MEDIA_LOADED is never generated and so
the play1 function is never activated. But I also found that Tim's
diagnosis of the source of the problem is correct: Play is called too soon
when the command comes right after Load. So I'm now looking for a way to
get the needed delay before calling play and would welcome suggestions.

Patrick

Thanks Jad, that works. It also works for me with the time at 100 (1/10 of a second) but not at 50 (1/20 of a second). A 1/10 of a second delay isn’t too bad, though of course there’s no guarantee that this will always be sufficient.

Patrick