#!@PYTHON@
# -*-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.
#
# $id$
#
# todo
# * 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
import gnome.ui
import gconf
# Gconf Paths
gc_options = "/apps/service-discovery-applet/options"
gc_services = "/apps/service-discovery-applet/services"
#from gettext import gettext as _
show_local_services = False
show_notifications = False
show_applet_name = False
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'
}
menuZC = gtk.ImageMenuItem()
menubar = gtk.MenuBar()
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))
if os.path.exists("@scriptsdir@/%s.sh" % type):
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)
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, notif, show_notifications
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):
pretty_name = zc_pretty_name[type]
else:
pretty_name = type
menuitem.add(gtk.Label(pretty_name))
img = gtk.Image()
iconfile = "@iconsdir@/24x24/%s.png" % (type)
if not os.path.exists(iconfile):
iconfile = "@iconsdir@/24x24/service-discovery-applet.png"
img.set_from_file(iconfile)
menuitem.set_image(img)
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()
iconfile = "@iconsdir@/48x48/%s.png" % (type)
if not os.path.exists(iconfile):
iconfile = "@iconsdir@/48x48/service-discovery-applet.png"
pretty_name = type
if zc_pretty_name.has_key(type):
pretty_name = zc_pretty_name[type]
message = "Name : %s\nType : %s (%s)" % (name,pretty_name, type)
try:
if show_notifications == True:
notif.Notify("Service Discovery Applet",
iconfile, dbus.UInt32(0),"",dbus.Byte(0),
"New Service found",message,
[iconfile],[""],[""],True,dbus.UInt32(3))
except:
print "can't use notification daemon"
pass
def remove_service(interface, protocol, name, type, domain):
global zc_services, notif, show_notifications
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]
iconfile = "@iconsdir@/48x48/%s.png" % (type)
if not os.path.exists(iconfile):
iconfile = "@iconsdir@/48x48/service-discovery-applet.png"
pretty_name = type
if zc_pretty_name.has_key(type):
pretty_name = zc_pretty_name[type]
message = "Name : %s\nType : %s (%s)" % (name, pretty_name, type)
try:
if show_notifications == True:
notif.Notify("Service Discovery Applet",
iconfile, dbus.UInt32(0),"",dbus.Byte(0),
"Service disappeared",message,
[iconfile],[""],[""],True,dbus.UInt32(3))
except:
print "can't use notification daemon"
pass
def add_service_type(interface, protocol, type, domain):
global server, service_browsers, system_bus
# 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(system_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 del_service_type(interface, protocol, type, domain):
service = (interface, protocol, type, domain)
if not service_browsers.has_key(service):
return
sb = service_browsers[service]
sb.Free()
del service_browsers[service]
# delete the sub menu of service_type
if zc_types.has_key(type):
service_menu.remove(zc_types[type].get_attach_widget())
del zc_types[type]
# Callback: panel background changed
def on_change_background(panelapplet, backgroundtype, color, pixmap):
global menubar, menuZC
panelapplet.modify_bg(gtk.STATE_NORMAL, color)
menuZC.modify_bg(gtk.STATE_NORMAL, color)
menubar.modify_bg(gtk.STATE_NORMAL, color)
if backgroundtype == gnomeapplet.PIXMAP_BACKGROUND:
print "PIXMAP_BACKGROUND"
s1 = panelapplet.get_style()
# s2 = menuZC.get_style()
# s3 = menubar.get_style()
s1.bg_pixmap[gtk.STATE_NORMAL] = pixmap
# s2.bg_pixmap[gtk.STATE_NORMAL] = pixmap
# s3.bg_pixmap[gtk.STATE_NORMAL] = pixmap
if backgroundtype == gnomeapplet.COLOR_BACKGROUND:
print "COLOR_BACKGROUP"
if backgroundtype == gnomeapplet.NO_BACKGROUND:
print "NO_BACKGROUND"
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
# This little hack is required to get Fitt's Law compliance -
# i.e. to get the Menubar to be the full height of the panel.
def on_menubar_size_allocate(menubar, rect):
if (rect.x <= 0) or (rect.y <= 0):
return False
rect.x -= 1
rect.y -= 1
rect.width += 2
rect.height += 2
gtk.Widget.size_allocate(menubar, rect)
return False
def on_about(component, verb, applet):
icon = gtk.Image()
icon.set_from_file("@iconsdir@/48x48/service-discovery-applet.png")
fullname = "Service Discovery Applet"
copyright = "Copyright (C) 2005 Sebastien Estienne"
description = "An applet to quickly access your zeroconf services."
authors = ["Sebastien Estienne "]
about = gnome.ui.About(fullname, "@version@", copyright, description, authors, None, None, icon.get_pixbuf())
about.set_icon(icon.get_pixbuf())
about.show()
def on_config(component, verb, applet):
os.system("service-discovery-config")
#FIXME replace with gconf key
def start_service_discovery(component, verb, applet):
global system_bus, server, db , gc_client, domain, interface, protocol
if len(domain) != 0:
return
try:
domain = server.GetDomainName()
except:
print "Check that Avahi daemon is running!"
return
interface = avahi.IF_UNSPEC
protocol = avahi.PROTO_UNSPEC
gc_entries = gc_client.all_entries(gc_services)
for gc_entry in gc_entries:
if gc_client.get_bool(gc_entry.key) == True:
service_type = os.path.basename(gc_entry.key)
add_service_type(interface, protocol, service_type, domain)
def stop_service_discovery(component, verb, applet):
global domain
if len(domain) == 0:
return
for service in service_browsers.copy():
del_service_type(service[0],service[1],service[2],service[3])
domain = ""
# Callback called when a service is added/removed/enabled/disabled in gconf
def gc_services_cb (client, cnxn_id, gc_entry, data):
global interface, domain, protocol
service_type = os.path.basename(gc_entry.key)
# FIXME unset key
if client.get_bool(gc_entry.key) == True:
# Browse for a new service
print "browse %s" % (service_type)
add_service_type(interface, protocol, service_type, domain)
else:
# Stop browsing for a service
print "remove %s" % (service_type)
del_service_type(interface, protocol, service_type, domain)
def gc_options_cb (client, cnxn_id, gc_entry, data):
global show_notifications, show_applet_name, show_local_services
key = os.path.basename(gc_entry.key)
if key == "show_applet_name":
show_applet_name = client.get_bool(gc_entry.key)
if key == "show_notifications":
show_notifications = client.get_bool(gc_entry.key)
if key == "show_local_services":
show_local_services = client.get_bool(gc_entry.key)
def ServiceDiscoveryApplet_factory(applet, iid):
global session_bus, notif, show_notifications, gc_client, server, system_bus, domain, menubar, menuZC
# Gconf
gc_client = gconf.client_get_default ()
gc_client.add_dir (gc_options, gconf.CLIENT_PRELOAD_NONE)
show_local_services = gc_client.get_bool ("%s/%s" % (gc_options,"show_local_services"))
show_notifications = gc_client.get_bool ("%s/%s" % (gc_options,"show_notifications"))
show_applet_name = gc_client.get_bool ("%s/%s" % (gc_options,"show_applet_name"))
gc_client.notify_add (gc_options, gc_options_cb, None)
gc_client.add_dir (gc_services, gconf.CLIENT_PRELOAD_NONE)
gc_client.notify_add (gc_services, gc_services_cb,None)
# Applet MenuItem
menuZC = gtk.ImageMenuItem()
menuZC.add(gtk.Label('ZeroConf'))
image = gtk.Image()
image.set_from_file("@iconsdir@/24x24/service-discovery-applet.png")
menuZC.set_image(image)
menuZC.set_right_justified(True)
menuZC.set_submenu(service_menu);
menuZC.show_all()
# Applet MenuBar
gtk.rc_parse_string('''
style "service-discovery-applet-menubar-style"
{
GtkMenuBar::shadow-type = none
GtkMenuBar::internal-padding = 0
}
widget "*.service-discovery-applet" style "service-discovery-applet-menubar-style"''')
menubar = gtk.MenuBar()
menubar.set_name("service-discovery-applet")
menubar.connect("button-press-event", on_menubar_click)
menubar.connect("size-allocate", on_menubar_size_allocate)
menubar.add(menuZC)
#expand the applet with the panel
# applet.connect("change_background", on_change_background)
applet.set_applet_flags(gnomeapplet.EXPAND_MINOR)
applet.add(menubar)
applet.show_all()
# funky right-click menu
menuXml = """
"""
applet.setup_menu(menuXml, [
("SDA About", on_about),
("SDA Config", on_config),
("SDA Start", start_service_discovery),
("SDA Stop", stop_service_discovery)
], applet)
popup = applet.get_popup_component()
#Start Service Discovery
domain = ""
system_bus = dbus.SystemBus()
server = dbus.Interface(system_bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER),
avahi.DBUS_INTERFACE_SERVER)
start_service_discovery(None, None, None)
session_bus = dbus.SessionBus()
obj = session_bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
notif = dbus.Interface(obj, "org.freedesktop.Notifications")
return True
print "Starting Service Discovery Applet"
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 "Service Discovery Applet ended"