wxPython and Gstreamer: two Mainloops?

Hi folks,

I have noticed a fair few posts on combining wxPython with GStreamer,
so hopefully someone on here can help me out.

I am having trouble combining the wx.App.MainLoop() and the GStreamer
event system. Only taking code from the GStreamer tutorial (
http://pygstdocs.berlios.de/pygst-tutorial/playbin.html ), I typically
have something like this in my code:

<inside class>

    self.bus = self.player.get_bus()
    self.bus.add_signal_watch()
    self.bus.enable_sync_message_emission()
    self.bus.connect("message", self.on_message)
    self.bus.glib.threads_init()

    def on_message(self, bus, message):
        t = message.type
        print t
        if t == gst.MESSAGE_EOS: # track is finished
            self.player.set_state(gst.STATE_NULL)
        elif t == gst.MESSAGE_ERROR:
            self.player.set_state(gst.STATE_NULL)
            err, debug = message.parse_error()
            print "Error: %s" % err, debug

Now, if I run the wx.App.MainLoop() first, I can't get to the
gst.events and if I run the gobject.Mainloop(), the GUI doesn't show
(obviously). I am still new to this, so I would be glad if one of you
could nudge me into the right direction. So far I have tried to use
threads of any kind with no luck (which does not necessarily mean I
used the threads correctly in the first place) and I did some research
and the best I could come up with were the following links:

http://stackoverflow.com/questions/815255/using-threads-and-pygst-in-a-wx-python-app

http://www.jejik.com/articles/2007/01/python-gstreamer_threading_and_the_main_loop/

but unfortunately, I do not understand, how this helps me with my two
mainloops problem. Now if this is at all possible, I am very grateful
for any help, you guys can offer.

Thanks a lot,

I have to adjust the code snippet that I have written. Remove this
line:

self.bus.glib.threads_init()

that line is nonsense and stems from a random desperation trial of
pasting strange lines into random location and praying :wink:

Also, I forgot to mention. I use Python 2.6 and wxPython 2.8 on a
Windows XP machine.

Sorry, for the addendum

···

On May 18, 2:29 am, Nebelhom <nebel...@googlemail.com> wrote:

Hi folks,

I have noticed a fair few posts on combining wxPython with GStreamer,
so hopefully someone on here can help me out.

I am having trouble combining the wx.App.MainLoop() and the GStreamer
event system. Only taking code from the GStreamer tutorial (Adminpanel), I typically
have something like this in my code:

<inside class>

self\.bus = self\.player\.get\_bus\(\)
self\.bus\.add\_signal\_watch\(\)
self\.bus\.enable\_sync\_message\_emission\(\)
self\.bus\.connect\(&quot;message&quot;, self\.on\_message\)
self\.bus\.glib\.threads\_init\(\)

def on\_message\(self, bus, message\):
    t = message\.type
    print t
    if t == gst\.MESSAGE\_EOS: \# track is finished
        self\.player\.set\_state\(gst\.STATE\_NULL\)
    elif t == gst\.MESSAGE\_ERROR:
        self\.player\.set\_state\(gst\.STATE\_NULL\)
        err, debug = message\.parse\_error\(\)
        print &quot;Error: %s&quot; % err, debug

Now, if I run the wx.App.MainLoop() first, I can't get to the
gst.events and if I run the gobject.Mainloop(), the GUI doesn't show
(obviously). I am still new to this, so I would be glad if one of you
could nudge me into the right direction. So far I have tried to use
threads of any kind with no luck (which does not necessarily mean I
used the threads correctly in the first place) and I did some research
and the best I could come up with were the following links:

multithreading - using threads and pyGST in a wx python app - Stack Overflow

Lone Wolves - Web, game, and open source development

but unfortunately, I do not understand, how this helps me with my two
mainloops problem. Now if this is at all possible, I am very grateful
for any help, you guys can offer.

Thanks a lot,

I don't know much about gstreamer, but perhaps if you share some of your attempt at a threading implementation (or provide a small runnable sample) then we'll be able to help out with the general principles. In a nutshell you should probably run the wx mainloop like normal, create a new thread for gstreamer and register whatever callbacks, etc. that it needs there and run its main(), or perhaps implement your own main loop as shown in the 2nd link. When the callbacks happen and you need to notify the UI thread then use wx.CallAfter or some other safe way to call some code in the UI thread.

Another source of help (or perhaps more confusion) would be to look at how gstreamer is used for a wxMediaCtrl backend for unix builds of wxWidgets: wxTrac has been migrated to GitHub Issues - wxWidgets

···

On 5/17/12 5:29 PM, Nebelhom wrote:

Hi folks,

I have noticed a fair few posts on combining wxPython with GStreamer,
so hopefully someone on here can help me out.

I am having trouble combining the wx.App.MainLoop() and the GStreamer
event system. Only taking code from the GStreamer tutorial (
Adminpanel ), I typically
have something like this in my code:

<inside class>

     self.bus = self.player.get_bus()
     self.bus.add_signal_watch()
     self.bus.enable_sync_message_emission()
     self.bus.connect("message", self.on_message)
     self.bus.glib.threads_init()

     def on_message(self, bus, message):
         t = message.type
         print t
         if t == gst.MESSAGE_EOS: # track is finished
             self.player.set_state(gst.STATE_NULL)
         elif t == gst.MESSAGE_ERROR:
             self.player.set_state(gst.STATE_NULL)
             err, debug = message.parse_error()
             print "Error: %s" % err, debug

Now, if I run the wx.App.MainLoop() first, I can't get to the
gst.events and if I run the gobject.Mainloop(), the GUI doesn't show
(obviously). I am still new to this, so I would be glad if one of you
could nudge me into the right direction. So far I have tried to use
threads of any kind with no luck (which does not necessarily mean I
used the threads correctly in the first place) and I did some research
and the best I could come up with were the following links:

multithreading - using threads and pyGST in a wx python app - Stack Overflow

Python-gstreamer, threading and the main loop - Lone Wolves - Web, game, and open source development

but unfortunately, I do not understand, how this helps me with my two
mainloops problem. Now if this is at all possible, I am very grateful
for any help, you guys can offer.

--
Robin Dunn
Software Craftsman

Hi,

thanks so much for the input. After playing around with threading and
conferring with someone on the German Python forum, I came up with a
solution that seems to work for me (For those interested and able to
read German here is the link http://www.python-forum.de/viewtopic.php?f=19&t=29287
). I have noticed that the gobject.MainLoop just needs to be run.
Where it runs seems to be immaterial, so I just created a separate
GobjectThread class and started the mainloop in that thread and
finished it after the wx.App.MainLoop() was exited.

Modelled on my original code, I created a minimal example that
hopefully demonstrates what I did. If you have any kind of input or
see a mistake, then please let me know. I am only a mere python
padawan, so I won't take offense, if you improve my code and I learn
something in the process :wink:

Thanks again for taking the time to help.

I apologise that the code is still a bit long, but mos of it is just
syntactic sugar. Oh and one more thing to note. The code "should" play
your audiofile immediately.

#!usr/bin/python

import os
import urllib
from threading import Thread

import wx
import pygst
pygst.require("0.10")
import gst
import gobject

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)

        self.player = GstPlayer()

        # Close Event
        self.Bind(wx.EVT_CLOSE, self.on_close)

        self.__set_properties()
        self.__do_layout()

    def on_close(self, event):
        # If state not set to NULL, Critical Error occurs on gobject
quit
        state = self.player.get_state()
        if state[1] == gst.STATE_PLAYING:
            self.player.set_state(gst.STATE_NULL)
        self.Destroy()

    def __set_properties(self):
        self.SetTitle("Test")

    def __do_layout(self):
        self.Layout()

class GstPlayer():
    def __init__(self):
        # This is almost straight out of the tutorial
        p = os.path.join("path", "to", "your", "audiofile")
        path = urllib.pathname2url(p)

        self.player = gst.element_factory_make("playbin2", "player")
        fakesink = gst.element_factory_make("fakesink", "fakesink")
        self.player.set_property("video-sink", fakesink)

        self.player.set_property("uri", "file:" + path)
        self.player.set_state(gst.STATE_PLAYING)

    def get_state(self):
        return self.player.get_state()

    def set_state(self, state):
        self.player.set_state(state)

class GobjectThread(Thread):
    def __init__(self):
        Thread.__init__(self)

···

##############################
        self.loop = gobject.MainLoop() # The mainloop to be separated
from wx
        ##############################

    def run(self): # Called on Thread.start()
        self.loop.run()

    def quit(self):
        # Stops the gobject Mainloop
        self.loop.quit()

if __name__ == "__main__":
    gobject.threads_init()

    t = GobjectThread()
    t.start()

    # wxGlade's my Friend here
    # Just basics
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame = MyFrame(None, -1, "")
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()

    t.quit() #End the gobject.MainLoop()