I am creating an application in python and gtk+ 3 that uses avahi to broadcast itself on the network. The program should publish itself on the network but also discover other instances of it , like an avahi client/server.
For the publishing and browsing of services on network i'm using dbus.SystemBus() daemon.
The publishing of service works , after i'm getting an interface object and adding the service, then it calls the Commit() method which does what i want.
For the service discovering part, i have to use a main loop which will asynchronously get the services that were published in the past and that will be published later:
loop = DBusGMainLoop()
self.bus = dbus.SystemBus(mainloop=loop)
.... and then I run a main loop to discover network services:
gobject.MainLoop().run()
Now here is the problem I'm encountering, when I start my gtk program, this also uses a main loop by calling: Gtk.main() , which probably interfere with the call from the avahi service. This gives the following error :
"""
RuntimeError: To make asynchronous calls, receive signals or export objects, D-Bus connections must be attached to a main loop by passing mainloop=... to the constructor or calling dbus.set_default_main_loop(...)
"""
How should I pass the GTK+ application's main loop to the avahi client so they can both share it.
Here is a small example from the code:
*** AvahiDiscover.py ***
class ServiceDiscover:
def __init__(self, stype='_http._tcp'):
self.domain = ""
self.stype = stype
def discover(self):
loop = DBusGMainLoop()
self.bus = dbus.SystemBus(mainloop=loop)
self.server = dbus.Interface( self.bus.get_object(avahi.DBUS_NAME, '/'),'org.freedesktop.Avahi.Server')
self.sbrowser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, self.stype, 'local', dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
self.sbrowser.connect_to_signal("ItemNew", self.handler) # handler method which print the services found
gobject.MainLoop().run()
*** MainWindow.py ***
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Geysigning")
# create a notebook container
notebook = Gtk.Notebook()
# ......
self.add(notebook)
self.connect("delete-event", Gtk.main_quit)
# setup service broadcast - this publishes the service on the network
service_publisher = ServicePublisher(name="GeysignService)
service_publisher.publish()
# setup service browsing
service_discover = ServiceDiscover(stype='_http._tcp')
service_discover.discover()
if __name__ == "__main__":
window = MainWindow()
window.show_all()
Gtk.main()