#!/usr/bin/python # EeePC Sync using unison # # Frederic Descamps # # 21 JAN 2009 # # v.0.3 # # Changelog # # 21 JAN 2009 - 0.3 - Status icon menu changed # 17 JAN 2009 - 0.2 - Status icon added + several error checks # 16 JAN 2009 - 0.1 - Initial release # # This program should run on the machine where you want to synchronize the EeePC # Both machines requires the following : # - unison installed # - a folder EeePC on ~/Desktop (you can change that name below via the variable 'folder' # - having ssh access to the EeePC via a key # # on the EeePC you need to have the following file : # - /etc/avahi/services/eeepc.service : # # # # # # # # # # # # %h # # # _eeepc._tcp # # # # import dbus, gobject, avahi from dbus import DBusException from dbus.mainloop.glib import DBusGMainLoop import pygtk pygtk.require('2.0') import gtk import os import sys from user import home TYPE = '_eeepc._tcp' global ip global folder folder='/Desktop/EeePC' try: import pynotify if pynotify.init("EeePC Synchronization Tool"): n = pynotify.Notification("EeePC Synchronization Tool Started", "Looking for your EeePC") n.set_urgency(pynotify.URGENCY_LOW) n.set_timeout(2000) n.show() else: print "there was a problem initializing the pynotify module" except: print "you don't seem to have pynotify installed" class StatusIcc: # activate callback def activate( self, widget, data=None): popupMenu = gtk.Menu() menuPopup1 = gtk.MenuItem ("Search...") menuPopup1.connect("activate",self.doit) popupMenu.add(menuPopup1) menuPopup2 = gtk.ImageMenuItem (gtk.STOCK_QUIT) menuPopup2.connect("activate",self.askpopup) popupMenu.add(menuPopup2) popupMenu.show_all() popupMenu.popup(None,None,None,1,0) #self.doit() # destroyer callback def destroyer(self, widget,response_id, data= None): if response_id == gtk.RESPONSE_OK: #gtk.main_quit() #gobject.MainLoop().quit() sys.exit() else: widget.hide() # popup callback def askpopup(self, button, widget=None, data=None): dialog = gtk.MessageDialog( parent = None, flags = gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_INFO, buttons = gtk.BUTTONS_OK_CANCEL, message_format = "Do you want to close EeePC Sync ?") dialog.set_title('EeePC Sync') dialog.connect('response', self.destroyer) dialog.show() def __init__(self): # create a new Status Icon self.staticon = gtk.StatusIcon() self.staticon.set_from_stock(gtk.STOCK_REFRESH) self.staticon.set_tooltip("Click to find EeePC & Sync") self.staticon.set_blinking(False) self.staticon.connect("activate", self.activate) #self.staticon.connect("popup_menu", self.askpopup) self.staticon.set_visible(True) # invoking the main() self.doit() gtk.main() def doit(self, data = None): def sync_cb(n, action): assert action == "sync" global ip global folder if os.path.exists(home+folder): print "Syncrhonizing with %s" % (ip) return_value = os.system("/usr/bin/unison -ui text -batch -sshargs '-o PreferredAuthentications=hostbased,publickey' ssh://" + ip + folder +" ~" + folder) print "return value = %s" % (return_value) if return_value == 0: title="EeePC Synchronized !" message="Your EeePC is now synchronized successfully !" elif return_value == 768: title="EeePC Not Synchronized !" message="You don't have access to this EeePC !\nYour ssh key is not installed on the remote EeePC or the remote folder (%s) doesn't exist." % (folder) else: title="EeePC Not Synchronized !" message="Unexpected Error during communication !!" else: title="EeePC Not Synchronized !" message="Your local folder %s%s does not exist !" % (home,folder) n.close() gtk.main_quit() n = pynotify.Notification(title, message) n.set_urgency(pynotify.URGENCY_LOW) n.set_timeout(pynotify.EXPIRES_DEFAULT) n.show() def default_cb(n, action): assert action == "default" n.close() gtk.main_quit() def service_resolved(*args): n = pynotify.Notification("EeePC Synchronization Tool", "Found one EeePC :\n %s ( %s )" % (args[2], args[7]) ) global ip ip = args[7] n.set_urgency(pynotify.URGENCY_LOW) n.set_timeout(0) n.set_category("device") n.add_action("sync", "Sync", sync_cb) n.add_action("default", "Default Action", default_cb) n.show() gtk.main() def print_error(*args): print 'error_handler' print args[0] def myhandler(interface, protocol, name, stype, domain, flags): if flags & avahi.LOOKUP_RESULT_LOCAL: # local service, skip pass server.ResolveService(interface, protocol, name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=service_resolved, error_handler=print_error) loop = DBusGMainLoop() bus = dbus.SystemBus(mainloop=loop) server = dbus.Interface( bus.get_object(avahi.DBUS_NAME, '/'), 'org.freedesktop.Avahi.Server') sbrowser = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, TYPE, 'local', dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER) sbrowser.connect_to_signal("ItemNew", myhandler) gobject.MainLoop().run() statusicon = StatusIcc()