diff options
Diffstat (limited to 'src/service-discovery-applet.in')
-rwxr-xr-x | src/service-discovery-applet.in | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/src/service-discovery-applet.in b/src/service-discovery-applet.in new file mode 100755 index 0000000..171f8c0 --- /dev/null +++ b/src/service-discovery-applet.in @@ -0,0 +1,219 @@ +#!@PYTHON@ + +# This file is part of service-discovery-applet (sd-applet). +# +# sd-applet is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# sd-applet is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with sd-applet; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +# todo +# * memleaks ? +# * dict([el.split('=',1) for el in l ]) + +import os +import sys +import pygtk +pygtk.require('2.0') + +try: + import avahi, gobject, dbus +except ImportError: + print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus." + sys.exit(1) + +try: + import dbus.glib +except ImportError, e: + pass + +import gtk +import gnomeapplet +import gnome + +domain = None + +type_browsed = ('_ssh._tcp', '_http._tcp','_ftp._tcp') + +service_browsers = {} +service_menu = gtk.Menu() +zc_types = {} +zc_services = {} +zc_pretty_name = {'_ssh._tcp' : 'SSH Servers', + '_http._tcp' : 'Web Servers', + '_ftp._tcp' : 'Ftp Servers', + '_workstation._tcp': 'Workstations' + } + + + +def siocgifname(interface): + global server + + if interface <= 0: + return "any" + else: + return server.GetNetworkInterfaceNameByIndex(interface) + +def service_resolved(interface, protocol, name, type, domain, host, aprotocol, address, port, txt): + print "Service data for service '%s' of type '%s' in domain '%s' on %s.%i:" % (name, type, domain, siocgifname(interface), protocol) + print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, avahi.txt_array_to_string_array(txt)) + cmd = '@scriptsdir@/%s.sh "%s" %s %s %i "%s"' % (type, name, host, address, port," ".join(avahi.txt_array_to_string_array(txt))) + os.system(cmd) +# if type == "_http._tcp": +# +# url = "http://%s:%i" % (address,port) +# gnome.url_show(url) +# else: +# os.system(cmd) + # FIXME: text if the script exist + +def print_error(err): + print "Error:", str(err) + +def menuitem_response(widget, interface, protocol, name, type, domain): + server.ResolveService(interface, protocol, name, type, domain, avahi.PROTO_UNSPEC, reply_handler=service_resolved, error_handler=print_error) + +def new_service(interface, protocol, name, type, domain): + global server, service_menu, zc_types, zc_pretty_name, zc_services + + print "Found service '%s' of type '%s' in domain '%s' on %s.%i." % (name, type, domain, siocgifname(interface), protocol) + + if zc_types.has_key(type) == False: + menuitem = gtk.ImageMenuItem() + if zc_pretty_name.has_key(type): + menuitem.add(gtk.Label(zc_pretty_name[type])) + img = gtk.Image() + iconfile = "@iconsdir@/%s.png" % (type) + img.set_from_file(iconfile) + menuitem.set_image(img) + else: + menuitem.add(gtk.Label(type)) + + service_menu.add(menuitem) + zc_types[type] = gtk.Menu() + menuitem.set_submenu(zc_types[type]) + menuitem.show_all() + + menuitem = gtk.MenuItem(name) + zc_types[type].add(menuitem) + zc_services[(interface, protocol, name, type, domain)] = menuitem + menuitem.connect("activate", menuitem_response,interface, protocol, name, type, domain) + menuitem.show_all() + + # Asynchronous resolving + #server.ResolveService(interface, protocol, name, type, domain, avahi.PROTO_UNSPEC, reply_handler=service_resolved, error_handler=print_error) + +def remove_service(interface, protocol, name, type, domain): + global zc_services + + print "Service '%s' of type '%s' in domain '%s' on %s.%i disappeared." % (name, type, domain, siocgifname(interface), protocol) + + zc_types[type].remove(zc_services[(interface, protocol, name, type, domain)]) + + if zc_types[type].get_children() == []: + service_menu.remove(zc_types[type].get_attach_widget()) + del zc_types[type] + +def new_service_type(interface, protocol, type, domain): + global server, service_browsers + + # Are we already browsing this domain for this type? + if service_browsers.has_key((interface, protocol, type, domain)): + return + + print "Browsing for services of type '%s' in domain '%s' on %s.%i ..." % (type, domain, siocgifname(interface), protocol) + + b = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.ServiceBrowserNew(interface, protocol, type, domain)), avahi.DBUS_INTERFACE_SERVICE_BROWSER) + b.connect_to_signal('ItemNew', new_service) + b.connect_to_signal('ItemRemove', remove_service) + + service_browsers[(interface, protocol, type, domain)] = b + +def browse_domain(interface, protocol, domain): + global server + + # Are we already browsing this domain? + for type in type_browsed: + new_service_type(interface, protocol, type, domain) + +def new_domain(interface, protocol, domain): + # We browse for .local anyway... + if domain != "local": + browse_domain(interface, protocol, domain) + + +bus = dbus.SystemBus() +server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER) + +if domain is None: + # Explicitly browse .local + browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local") + + # Browse for other browsable domains + db = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE)), avahi.DBUS_INTERFACE_DOMAIN_BROWSER) + db.connect_to_signal('ItemNew', new_domain) + +else: + # Just browse the domain the user wants us to browse + browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain) + +def on_menubar_click(widget, event): + # allow Middle- and Right-Mouse-Button to go through to the applet window + if event.button != 1: + widget.emit_stop_by_name("button-press-event") + + return False + + +def ServiceDiscoveryApplet_factory(applet, iid): + global menuZC + print "Creating new applet instance" + menubar = gtk.MenuBar() + menubar.connect("button-press-event", on_menubar_click) + + menuZC = gtk.ImageMenuItem() + menuZC.add(gtk.Label('ZeroConf')) + img = gtk.Image() + img.set_from_file("@iconsdir@/service-discovery-applet-mini.png") + menuZC.set_image(img) + menuZC.set_right_justified(True) + menubar.add(menuZC) + menuZC.set_submenu(service_menu); + menuZC.show_all() + + + applet.add(menubar) + applet.show_all() + return True + + + +print "Starting factory" +if __name__ == '__main__': + if len(sys.argv) == 2 and sys.argv[1] == "-window": + main_window = gtk.Window(gtk.WINDOW_TOPLEVEL) + main_window.set_title("Service discovery applet") + main_window.connect("destroy", gtk.main_quit) + app = gnomeapplet.Applet() + ServiceDiscoveryApplet_factory(app, None) + app.reparent(main_window) + main_window.show_all() + gtk.main() + sys.exit() + else: + gnomeapplet.bonobo_factory("OAFIID:GNOME_ServiceDiscoveryApplet_Factory", + gnomeapplet.Applet.__gtype__, + "Service discovery applet", "0", ServiceDiscoveryApplet_factory) + +print "Factory ended" |