views:

618

answers:

3

OK, so I am writing an app, which plays music with the pyGST bindings.

This requires the use of threads to handle playback. The bindings library handles most of the thread control for me, which is nice(and what I was looking for in them).

Now, I don't have a full grasp on this concept, so I would be eager for some references. But the way I understand it, is I have to basically inform the app that it can use multiple threads.

I gathered this from the examples on the gstreamer site, where they use this call:

gtk.gdk.threads_init()  
gtk.main()

according to here, this tells the app it can use multiple threads(more or less), which is where my above assumption came from.

That is the background. Now get this. I have placed those lines in my code, and they work fine. My app plays music rather than crashing whenever it tries. But something doesn't feel right.
In the examples that I got those lines from, they use gtk for the whole GUI, but I want to use wxWidgets, so it feels wrong calling this gtk function to do this.

Is there a wx equivalent to this? or is it ok to use this, and will it still work cross platform?

Also, I have to figure out how to kill all these threads on exit(which it does not do right now) I see how they do it in the example using a gtk method again, so again, looking for a wx equivalent.

PS: I think this(or the solution) may be related to the wx.App.MainLoop() function, but I am lost in trying to understand how this loop works, so again, good references about this would be appreciated, but I suppose not necessary as long as I have a good solution.

A: 

I have no experience with pyGST, but the general advice for using threads and wxPython is to only update the GUI from the main thread (i.e. the thread that starts the MainLoop). See http://wiki.wxpython.org/LongRunningTasks for more information.

Frank Niessink
yeah, this is kind of the track I was on with the MainLoop. I just have to do some digging I guess for the pyGST events and such. I'll be sure to give you this one if it works out.Thanks, glad someone finally gave a shot at an answer.
gnomed
A: 

I have no experience with the python bindings, but I have had success using wxWidgets and GStreamer together on Windows. The problem is that wxWidgets runs a Windows event loop while GStreamer uses a GLib event loop. If you don't care about any of the GStreamer events, you shouldn't need to do anything. However, if you care to receive any of the GStreamer events, you will have to run your own GLib event loop (GMainLoop) in a separate thread with a separate GMainContext. Use gst_bus_create_watch to create a GST event source, add a callback to the source with g_source_set_callback, and then attach it to the main context of your GLib event loop with g_source_attach. You can then handle the GST in the callback, for example, to forward the events to the wx main event loop.

I like the idea of not having to do anything, and I dont really "care" about the events. but my problem is that whenever I try to start playing("playbin.set_state(gst.STATE_PLAYING)") something with GStreamer it only plays as long as that method(that is setting the state) is active, which means the GUI can't do anything else while its playing, and I would have to insert something like a empty loop just to keep the method active to hear something(it took me forever to even find this was my problem). otherwise the method returns before I hear a peep. :s
gnomed
Really? set_state has always been non-blocking with any of the GStreamer elements I have used. Are you calling gtk.main() from the GUI thread because that will block. If set_state is indeed blocking, you can subclass wxThread and override the Entry method to call set_state. Then, from the GUI, do a thread.Create() followed by thread.Run() to start the thread. Hope this helps.
I dont have this problem when I call gtk.main() (along with gtk.thread_init()) But like I say above, I dont like the idea of using gtk specifically, I want it to be non-blocking without having to call this, and sticking to the wx API.
gnomed
+1  A: 

Try using this instead:

import gobject
gobject.threads_init()

I wonder how come it is not written in large print at the start of every python gstreamer plugin piece of documentation: it only took me several hours to find it.

A bit more details here.

I guess that solves that. it kind of implies that it makes no difference if I use the gtk method or the gobject one. but oh well.
gnomed