I am trying to integrate GTK (in a .NET application via the gtk-sharp bindings) into an application that already has a "main loop." Calling Gtk.Application.Run() results in the entire thing basically locking up while waiting on the Gtk loop. Furthermore, this app can't really be integrated into GTK in the usual sense (that is, using GTK's idle stuff to pump the app for events).
Is there a way to do the opposite and run the GTK main event loop manually?
Right now I have something like this:
def _pump_gtk():
while true:
if Gtk.Application.EventsPending():
Gtk.Application.RunIteration()
yield
(the yield is because _pump_gtk is running as a coroutine in the main application)
However, this seems to have problems because Gtk doesn't think there is a main loop running? I get a lot of Gtk-CRITICAL **: gtk_main_quit: assertion main_loops != NULL' failed errors.
Is there a way to run the GTK main loop manually?
Related
I have a C++ program that I used this simple gtk code at first of my main() function, and my goal is my app shows an image when it started and keeping showing the image and keep the rest of program.
GtkWidget* window;
GtkWidget* image1;
GtkWidget* image2;
gtk_init (NULL,NULL);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image1 = gtk_image_new_from_file("1.jpg");
image2 = gtk_image_new_from_file("2.jpg");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
gtk_container_add(GTK_CONTAINER (window), image1);
gtk_widget_show_all(window);
gtk_main();
THE REST OF PROGRAM THAT WONT EXECUTE!
But when it opens a window and shows the image, it stuck there and doesn't execute the rest of code! Why this happens?
After you execute gtk_main, your code will "block", if i can say that, in that line until gtk_main_quit it's called/executed.
This is the nature of graphical user interfaces. Typically, you setup everything, call the main loop and wait for user interaction.
I would suggest that you read GNOME's Getting Started with GTK+.
As an example, if you do any printf below gtk_main, it will get printed after you close the GtkWindow.
Your application logic must be defined previously, then by means of user interaction, pressing buttons and other widgets, the application will do "things".
When you call gtk_main, the main loop starts.
The main event loop manages all the available sources of events for
GLib and GTK+ applications. These events can come from any number of
different types of sources such as file descriptors (plain files,
pipes or sockets) and timeouts.
You can read more about it here.
I made a code through python to operate a preview of my PiCamera, I have set the time to 10 seconds, then automatically turns off. However I am unsure how I would be able to have a keystroke to stop the camera and return to the previous screen?
At the moment I am able to view for 10 seconds, and nothing else, the usual ctrl-c and various other keys does not work.
How would I be able to integrate a keystroke into the code following to stop the script and return to normal screen?
from picamera import PiCamera
from time import sleep
camera = PiCamera()
camera.start_preview()
sleep(10)
camera.stop_preview()
Subprocess module you can check on the official page:
https://docs.python.org/2/library/subprocess.html#subprocess.Popen
A possible way to implement with subprocess.Popen is here on SO:
Controlling a python script from another script
Another possibility is to use multiprocesses or multithreading module. For instance creation of a thread can be done and you can take care of an ID :-)
All the possibility will lead you to learn a bit more of python!
My better suggestion will be to create easily a thread (https://docs.python.org/3/library/threading.html --> here for python 3), get the ID and leave it run.
If you want to terminate the camera running, then terminate the thread :-)
I'm writing a small custom player based on libvlc. I've used much of the code from https://github.com/hartror/python-libvlc-bindings/blob/master/examples/gtkvlc.py that plays a single track just like I need.
Now I want to swtich to another track after previous has finished. To do that I catch callback "EventType.MediaPlayerEndReached" and in callback handler I write code:
<------>def endCallback(self,event):
<------><------>fname = vlc_controller.GetNextTrack()['url']
<------><------>self.w.set_title(fname)
<------><------>self.vlc.player.set_mrl(fname)
<------><------>self.w.set_title('after set_mrl')
<------><------>self.vlc.player.play()
<------><------>self.w.set_title('after play')
Now when this code gets executed it stucks on self.vlc.player.set_mrl(fname) and does not go any further and as a result I see NO NEXT TRACK.
I've tried different variations of this code using (vlc.stop(), vlc.set_media instead of vlc.set_mrl) but nothing works
Finally....
I think the best choise is to make multi threaded application on python
2 Threads:
Main thread - gtk.loop and displaying video an some other thinks
Additional thread that makes media switching.
For some time I was afraid of multithreading but now I know that this was the best way to do this task
For those facing similar issue in C# (Xamarin), per VLC documentation, calling the VLC object from an event tied to the object may freeze the application. So they said to use the code below inside the trigger event.
ThreadPool.QueueUserWorkItem(_ => PlayNext());
An example would be calling the code above inside the EndReach event.
Where PlayNext() is your own custom method to handle the next action you want to execute.
I struggled with this for about a day before seeing that portion of the documentation.
I have console applicaiotn that currently uses CAsyncSocket.
I need to implement SSL so after some searching I found this project: http://www.codeproject.com/Articles/3915/CAsyncSslSocketLayer-SSL-layer-class-for-CAsyncSoc
For some reason same simple code that works fine on GUI code does not work in console app.
Has anyone exp. with CAsyncSslSocketLayer ?
Thanks.
CAsyncSocketEx uses a window as a sort of cheap thread to handle the event notifications that come from select(). Unfortunately, if you don't have a message loop, then the window which it creates will not receive these events.
http://support.microsoft.com/kb/90975
This article explains that a call to CreateWindow() needs to be called from a thread which has a message loop. And if you don't, then anything sent via PostMessage() won't get there.
I've recently started to tinker with this -- I want to remove the annoying hidden window and replace it with a normal thread. Their code relies on WSAAsyncSelect() in order to receive socket events... to a window. Yuk!
It's been a while since I had the same problem, but if I remember correctly, to use CAsyncSocket in a console app you need to add something like DECLARE_CONSOLEAPP (first two links shown below) to your console app. This should give your console a message pump to generate the socket notifications (OnReceive, etc.) GUI apps have these pumps but console apps don't, generally. The third (msdn) link below might also apply, it has more info and a different way.
If these still don't work, you should put breakpoints in your socket code and make sure your socket isn't instantiated in a thread or callback other than the main console app (the one that now has the message pump).
I think googling around for 'CAsyncSocket WinApp' or 'CAsyncSocket console app' would show more.
http://www.codeguru.com/cpp/misc/misc/consoleapps/article.php/c243/Console-app-using-MFC.htm
http://troels.knakkergaard.dk/code.htm
http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/a6f1b72a-21d8-4046-a3dc-d7d29ece2ef6
So I have been pulling my hair out all day at this, and I am out of patience.
Basically I have a pygtk program that is built from glade. At the bottom of the main window, there is a status bar that I use to display usage errors, and status messages about the connected hardware and they use the functions below. So all of the calls to displayError come from within my object based on user interaction, and they all seem to work. In testing I tried making calls to displayCurrent and it works as well. The problem comes when the hardware process tries to use displayCurrent. The way the system works is that one of the members of my main window class is an interface object to the hardware. This has a separate process, using multiprocessing.Process, which sends a signal every time it gets data with the data being the message to output. Does anyone have any ideas? I'll be happy to explain anything in more depth if needed, it's just a LOT of code to post to get all the details.
def displayCurrent(self, message):
print message
if self.lastMess:
self.statusBar.remove(self.normalID, self.lastMess)
self.lastMess = self.statusBar.push(self.normalID, message)
def displayError(self, message, timeout = 5):
"""
Function that takes an error message and raises it to the user via the statusbar
timeout seconds later.
"""
print message
mess = self.statusBar.push(self.urgentID, message)
# clear statusbar
gobject.timeout_add_seconds(timeout, self.clearStatus, self.urgentID, mess)
def clearStatus(self, cID, mID):
#time.sleep(timeout)
self.statusBar.remove(cID, mID)
#print self.statusBar.remove_all(self.urgentID)
print 'popped'
return False
Post the whole code.
In general, this won't work if you are in a separate process. GTK (and everything else) has been forked. You need to use some form of interprocess communication. Multiprocessing module handles it for you. There are also hacks you can do in GTK such as using a window title (like Vim) or perhaps a plug and socket to communicate; don't be tempted by these.