Ejemplo n.º 1
0
class OP2Daemon(object):
    __metaclass__ = Singleton
    implements(IObserver)

    def __init__(self):
        self.application = SIPApplication()
        self.stopping = False
        self.stop_event = Event()

        Account.register_extension(AccountExtension)
        BonjourAccount.register_extension(BonjourAccountExtension)
        SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension)

        self.account_model = AccountModel()
        self.bonjour_services = BonjourServices()
        self.hal = HardwareAbstractionLayer()
        self.session_manager = SessionManager()
        self.web_handler = WebHandler()

    def start(self):
        self.account_model.start()
        self.bonjour_services.start()
        self.hal.start()
        self.session_manager.start()
        notification_center = NotificationCenter()
        notification_center.add_observer(self)
        notification_center.add_observer(self, sender=self.application)
        self.application.start(FileStorage(ApplicationData.directory))

    def stop(self):
        if self.stopping:
            return
        self.stopping = True
        self.session_manager.stop()
        self.hal.stop()
        self.bonjour_services.stop()
        self.account_model.stop()
        self.application.stop()

    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    def _NH_SIPApplicationDidStart(self, notification):
        log.msg('SIP application started')
        self.web_handler.start()

    def _NH_SIPApplicationWillEnd(self, notification):
        self.web_handler.stop()

    def _NH_SIPApplicationDidEnd(self, notification):
        log.msg('SIP application ended')
        self.stop_event.set()
Ejemplo n.º 2
0
    def applicationShouldTerminate_(self, sender):
        if self.terminating:
            return True

        self.terminating = True
        BlinkLogger().log_info('Application will be terminated')
        NSThread.detachNewThreadSelector_toTarget_withObject_("killSelfAfterTimeout:", self, None)
        NotificationCenter().post_notification("BlinkShouldTerminate", None)
        NotificationCenter().add_observer(self, name="SIPApplicationDidEnd")
        app = SIPApplication()
        app.stop()

        import Profiler
        Profiler.stop(os.path.join(ApplicationData.directory, 'logs', 'profiler.stats'))
        return False
Ejemplo n.º 3
0
class Blink(QApplication):
    __metaclass__ = QSingleton

    implements(IObserver)

    def __init__(self):
        super(Blink, self).__init__(sys.argv)
        self.application = SIPApplication()
        self.auxiliary_thread = AuxiliaryThread()
        self.first_run = False
        self.main_window = MainWindow()

        self.update_manager = UpdateManager()
        self.main_window.check_for_updates_action.triggered.connect(self.update_manager.check_for_updates)
        self.main_window.check_for_updates_action.setVisible(self.update_manager != Null)

        Account.register_extension(AccountExtension)
        BonjourAccount.register_extension(BonjourAccountExtension)
        SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension)
        session_manager = SessionManager()
        session_manager.initialize(self.main_window, self.main_window.session_model)

    def run(self):
        from blink.util import call_in_gui_thread as call_later
        call_later(self._initialize_sipsimple) # initialize sipsimple after the qt event loop is started
        self.auxiliary_thread.start()
        self.exec_()
        self.update_manager.shutdown()
        self.application.stop()
        self.application.thread.join()
        log_manager = LogManager()
        log_manager.stop()

    def fetch_account(self):
        filename = os.path.expanduser('~/.blink_account')
        if not os.path.exists(filename):
            return
        try:
            data = open(filename).read()
            data = cjson.decode(data.replace(r'\/', '/'))
        except (OSError, IOError), e:
            print "Failed to read json data from ~/.blink_account: %s" % e
            return
        except cjson.DecodeError, e:
            print "Failed to decode json data from ~/.blink_account: %s" % e
            return
Ejemplo n.º 4
0
class Blink(QApplication, metaclass=QSingleton):
    def __init__(self):
        super(Blink, self).__init__(sys.argv)
        self.setAttribute(Qt.AA_DontShowIconsInMenus, False)
        self.sip_application = SIPApplication()
        self.first_run = False

        self.setOrganizationDomain("ag-projects.com")
        self.setOrganizationName("AG Projects")
        self.setApplicationName("Blink")
        self.setApplicationVersion(__version__)

        self.main_window = MainWindow()
        self.chat_window = ChatWindow()
        self.main_window.__closed__ = True
        self.chat_window.__closed__ = True
        self.main_window.installEventFilter(self)
        self.chat_window.installEventFilter(self)

        self.main_window.addAction(
            self.chat_window.control_button.actions.main_window)
        self.chat_window.addAction(self.main_window.quit_action)
        self.chat_window.addAction(self.main_window.help_action)
        self.chat_window.addAction(self.main_window.redial_action)
        self.chat_window.addAction(self.main_window.join_conference_action)
        self.chat_window.addAction(self.main_window.mute_action)
        self.chat_window.addAction(self.main_window.silent_action)
        self.chat_window.addAction(self.main_window.preferences_action)
        self.chat_window.addAction(self.main_window.transfers_window_action)
        self.chat_window.addAction(self.main_window.logs_window_action)
        self.chat_window.addAction(
            self.main_window.received_files_window_action)
        self.chat_window.addAction(self.main_window.screenshots_window_action)

        self.ip_address_monitor = IPAddressMonitor()
        self.log_manager = LogManager()
        self.presence_manager = PresenceManager()
        self.session_manager = SessionManager()
        self.update_manager = UpdateManager()

        # Prevent application from exiting after last window is closed if system tray was initialized
        if self.main_window.system_tray_icon:
            self.setQuitOnLastWindowClosed(False)

        self.main_window.check_for_updates_action.triggered.connect(
            self.update_manager.check_for_updates)
        self.main_window.check_for_updates_action.setVisible(
            self.update_manager != Null)

        if getattr(sys, 'frozen', False):
            XMLDocument.schema_path = Resources.get('xml-schemas')

        Account.register_extension(AccountExtension)
        BonjourAccount.register_extension(BonjourAccountExtension)
        Contact.register_extension(ContactExtension)
        Group.register_extension(GroupExtension)
        SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension)

        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.sip_application)

        branding.setup(self)

    def run(self):
        self.first_run = not os.path.exists(ApplicationData.get('config'))
        self.sip_application.start(FileStorage(ApplicationData.directory))
        self.exec_()
        self.update_manager.shutdown()
        self.sip_application.stop()
        self.sip_application.thread.join()
        self.log_manager.stop()

    def quit(self):
        self.chat_window.close()
        self.main_window.close()
        super(Blink, self).quit()

    def eventFilter(self, watched, event):
        if watched in (self.main_window, self.chat_window):
            if event.type() == QEvent.Show:
                watched.__closed__ = False
            elif event.type() == QEvent.Close:
                watched.__closed__ = True
                if self.main_window.__closed__ and self.chat_window.__closed__:
                    # close auxiliary windows
                    self.main_window.conference_dialog.close()
                    self.main_window.filetransfer_window.close()
                    self.main_window.preferences_window.close()
        return False

    def customEvent(self, event):
        handler = getattr(self, '_EH_%s' % event.name, Null)
        handler(event)

    def _EH_CallFunctionEvent(self, event):
        try:
            event.function(*event.args, **event.kw)
        except:
            log.exception(
                'Exception occurred while calling function %s in the GUI thread'
                % event.function.__name__)

    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    def _NH_SIPApplicationWillStart(self, notification):
        self.log_manager.start()
        self.presence_manager.start()

    @run_in_gui_thread
    def _NH_SIPApplicationDidStart(self, notification):
        self.ip_address_monitor.start()
        self.main_window.show()
        accounts = AccountManager().get_accounts()
        if not accounts or (self.first_run and accounts == [BonjourAccount()]):
            self.main_window.preferences_window.show_create_account_dialog()
        self.update_manager.initialize()

    def _NH_SIPApplicationWillEnd(self, notification):
        self.ip_address_monitor.stop()

    def _NH_SIPApplicationDidEnd(self, notification):
        self.presence_manager.stop()

    @run_in_gui_thread
    def _NH_SIPApplicationGotFatalError(self, notification):
        log.error('Fatal error:\n{}'.format(notification.data.traceback))
        QMessageBox.critical(
            self.main_window, "Fatal Error",
            "A fatal error occurred, {} will now exit.".format(
                self.applicationName()))
        sys.exit(1)
Ejemplo n.º 5
0
class Blink(QApplication):
    __metaclass__ = QSingleton

    implements(IObserver)

    def __init__(self):
        super(Blink, self).__init__(sys.argv)
        self.setAttribute(Qt.AA_DontShowIconsInMenus, False)
        self.sip_application = SIPApplication()
        self.first_run = False

        self.setOrganizationDomain("ag-projects.com")
        self.setOrganizationName("AG Projects")
        self.setApplicationName("Blink")
        self.setApplicationVersion(__version__)

        self.main_window = MainWindow()
        self.chat_window = ChatWindow()
        self.main_window.__closed__ = True
        self.chat_window.__closed__ = True
        self.main_window.installEventFilter(self)
        self.chat_window.installEventFilter(self)

        self.main_window.addAction(self.chat_window.control_button.actions.main_window)
        self.chat_window.addAction(self.main_window.quit_action)
        self.chat_window.addAction(self.main_window.help_action)
        self.chat_window.addAction(self.main_window.redial_action)
        self.chat_window.addAction(self.main_window.join_conference_action)
        self.chat_window.addAction(self.main_window.mute_action)
        self.chat_window.addAction(self.main_window.silent_action)
        self.chat_window.addAction(self.main_window.preferences_action)
        self.chat_window.addAction(self.main_window.transfers_window_action)
        self.chat_window.addAction(self.main_window.logs_window_action)
        self.chat_window.addAction(self.main_window.received_files_window_action)
        self.chat_window.addAction(self.main_window.screenshots_window_action)

        self.ip_address_monitor = IPAddressMonitor()
        self.log_manager = LogManager()
        self.presence_manager = PresenceManager()
        self.session_manager = SessionManager()
        self.update_manager = UpdateManager()

        # Prevent application from exiting after last window is closed if system tray was initialized
        if self.main_window.system_tray_icon:
            self.setQuitOnLastWindowClosed(False)

        self.main_window.check_for_updates_action.triggered.connect(self.update_manager.check_for_updates)
        self.main_window.check_for_updates_action.setVisible(self.update_manager != Null)

        if getattr(sys, "frozen", False):
            XMLDocument.schema_path = Resources.get("xml-schemas")

        Account.register_extension(AccountExtension)
        BonjourAccount.register_extension(BonjourAccountExtension)
        Contact.register_extension(ContactExtension)
        Group.register_extension(GroupExtension)
        SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension)

        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.sip_application)

        branding.setup(self)

    def run(self):
        self.first_run = not os.path.exists(ApplicationData.get("config"))
        self.sip_application.start(FileStorage(ApplicationData.directory))
        self.exec_()
        self.update_manager.shutdown()
        self.sip_application.stop()
        self.sip_application.thread.join()
        self.log_manager.stop()

    def quit(self):
        self.chat_window.close()
        self.main_window.close()
        super(Blink, self).quit()

    def eventFilter(self, watched, event):
        if watched in (self.main_window, self.chat_window):
            if event.type() == QEvent.Show:
                watched.__closed__ = False
            elif event.type() == QEvent.Close:
                watched.__closed__ = True
                if self.main_window.__closed__ and self.chat_window.__closed__:
                    # close auxiliary windows
                    self.main_window.conference_dialog.close()
                    self.main_window.filetransfer_window.close()
                    self.main_window.preferences_window.close()
        return False

    def customEvent(self, event):
        handler = getattr(self, "_EH_%s" % event.name, Null)
        handler(event)

    def _EH_CallFunctionEvent(self, event):
        try:
            event.function(*event.args, **event.kw)
        except:
            log.exception("Exception occurred while calling function %s in the GUI thread" % event.function.__name__)

    def handle_notification(self, notification):
        handler = getattr(self, "_NH_%s" % notification.name, Null)
        handler(notification)

    def _NH_SIPApplicationWillStart(self, notification):
        self.log_manager.start()
        self.presence_manager.start()

    @run_in_gui_thread
    def _NH_SIPApplicationDidStart(self, notification):
        self.ip_address_monitor.start()
        self.main_window.show()
        accounts = AccountManager().get_accounts()
        if not accounts or (self.first_run and accounts == [BonjourAccount()]):
            self.main_window.preferences_window.show_create_account_dialog()
        self.update_manager.initialize()

    def _NH_SIPApplicationWillEnd(self, notification):
        self.ip_address_monitor.stop()

    def _NH_SIPApplicationDidEnd(self, notification):
        self.presence_manager.stop()

    @run_in_gui_thread
    def _NH_SIPApplicationGotFatalError(self, notification):
        log.error("Fatal error:\n{}".format(notification.data.traceback))
        QMessageBox.critical(
            self.main_window,
            u"Fatal Error",
            u"A fatal error occurred, {} will now exit.".format(self.applicationName()),
        )
        sys.exit(1)
Ejemplo n.º 6
0
class Blink(QApplication):
    __metaclass__ = QSingleton

    implements(IObserver)

    def __init__(self):
        super(Blink, self).__init__(sys.argv)
        self.setAttribute(Qt.AA_DontShowIconsInMenus, False)
        self.sip_application = SIPApplication()
        self.first_run = False

        self.setOrganizationDomain("ag-projects.com")
        self.setOrganizationName("AG Projects")
        self.setApplicationName("Blink")
        self.setApplicationVersion(__version__)

        self.main_window = MainWindow()
        self.chat_window = ChatWindow()
        self.main_window.__closed__ = True
        self.chat_window.__closed__ = True
        self.main_window.installEventFilter(self)
        self.chat_window.installEventFilter(self)

        self.main_window.addAction(self.chat_window.control_button.actions.main_window)
        self.chat_window.addAction(self.main_window.quit_action)
        self.chat_window.addAction(self.main_window.help_action)
        self.chat_window.addAction(self.main_window.redial_action)
        self.chat_window.addAction(self.main_window.join_conference_action)
        self.chat_window.addAction(self.main_window.mute_action)
        self.chat_window.addAction(self.main_window.silent_action)
        self.chat_window.addAction(self.main_window.preferences_action)
        self.chat_window.addAction(self.main_window.transfers_window_action)
        self.chat_window.addAction(self.main_window.logs_window_action)
        self.chat_window.addAction(self.main_window.received_files_window_action)
        self.chat_window.addAction(self.main_window.screenshots_window_action)

        self.ip_address_monitor = IPAddressMonitor()
        self.log_manager = LogManager()
        self.presence_manager = PresenceManager()
        self.session_manager = SessionManager()
        self.update_manager = UpdateManager()

        # Prevent application from exiting after last window is closed if system tray was initialized
        if self.main_window.system_tray_icon:
            self.setQuitOnLastWindowClosed(False)

        self.main_window.check_for_updates_action.triggered.connect(self.update_manager.check_for_updates)
        self.main_window.check_for_updates_action.setVisible(self.update_manager != Null)

        if getattr(sys, 'frozen', False):
            XMLDocument.schema_path = Resources.get('xml-schemas')

        Account.register_extension(AccountExtension)
        BonjourAccount.register_extension(BonjourAccountExtension)
        Contact.register_extension(ContactExtension)
        Group.register_extension(GroupExtension)
        SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension)

        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.sip_application)

        branding.setup(self)

    def run(self):
        self.first_run = not os.path.exists(ApplicationData.get('config'))
        self.sip_application.start(FileStorage(ApplicationData.directory))
        self.exec_()
        self.update_manager.shutdown()
        self.sip_application.stop()
        self.sip_application.thread.join()
        self.log_manager.stop()

    def quit(self):
        self.chat_window.close()
        self.main_window.close()
        super(Blink, self).quit()

    def fetch_account(self):
        filename = os.path.expanduser('~/.blink_account')
        if not os.path.exists(filename):
            return
        try:
            data = open(filename).read()
            data = cjson.decode(data.replace(r'\/', '/'))
        except (OSError, IOError), e:
            print "Failed to read json data from ~/.blink_account: %s" % e
            return
        except cjson.DecodeError, e:
            print "Failed to decode json data from ~/.blink_account: %s" % e
            return
Ejemplo n.º 7
0
class XCAPApplication(object):
    __metaclass__ = Singleton
    implements(IObserver)

    def __init__(self):
        self.application = SIPApplication()
        self.xcap_manager = None

        self.quit_event = Event()

        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.application)

    def start(self):
        self.application.start(FileBackend(os.path.realpath('test-config')))

    @run_in_green_thread
    def stop(self):
        self.xcap_manager.stop()
        self.application.stop()

    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    @run_in_green_thread
    def _NH_SIPApplicationDidStart(self, notification):
        account_manager = AccountManager()
        self.xcap_manager = XCAPManager(account_manager.default_account)
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.xcap_manager)
        self.xcap_manager.load(os.path.realpath('xcap-cache'))
        self.xcap_manager.start()

    def _NH_SIPApplicationDidEnd(self, notification):
        self.quit_event.set()

    def _NH_XCAPManagerDidChangeState(self, notification):
        print 'XCAP Manager state %s -> %s' % (notification.data.prev_state, notification.data.state)

    def _NH_XCAPManagerWillStart(self, notification):
        print 'XCAP Manager will start'

    def _NH_XCAPManagerDidStart(self, notification):
        print 'XCAP Manager did start'

    def _NH_XCAPManagerDidDiscoverServerCapabilities(self, notification):
        print '  contact list supported: %s' % notification.data.contactlist_supported
        print '  presence policies supported: %s' % notification.data.presence_policies_supported
        print '  dialoginfo policies supported: %s' % notification.data.dialoginfo_policies_supported
        print '  status icon supported: %s' % notification.data.status_icon_supported
        print '  offline status supported: %s' % notification.data.offline_status_supported

    def _NH_XCAPManagerWillEnd(self, notification):
        print 'XCAP Manager will end'

    def _NH_XCAPManagerDidEnd(self, notification):
        print 'XCAP Manager did end'

    def _NH_XCAPManagerDidReloadData(self, notification):
        print 'XCAP Manager reloaded data:'
        groups = dict.fromkeys(notification.data.groups)
        for group in groups:
            groups[group] = []
        for contact in notification.data.contacts:
            if contact.group is not None:
                groups[contact.group].append(contact)
        print 'Buddies:'
        for group, contacts in groups.iteritems():
            print '  %s:' % group
            for contact in contacts:
                if contact.name:
                    print '    %s <%s>' % (contact.name, contact.uri)
                else:
                    print '    %s' % contact.uri
                print '      subscribe-to-presence    = %s' % contact.subscribe_to_presence
                print '      subscribe-to-dialoginfo  = %s' % contact.subscribe_to_dialoginfo
                print '      presence-policies        = %s' % (', '.join(p.id for p in contact.presence_policies) if contact.presence_policies else None)
                print '      dialoginfo-policies      = %s' % (', '.join(p.id for p in contact.dialoginfo_policies) if contact.dialoginfo_policies else None)
                for attr, value in contact.attributes.iteritems():
                    print '      x: %s = %s' % (attr, value)
            print

        print 'Presence policies:'
        for policy in notification.data.presence_policies:
            print '  %s -> %s' % (policy.id, policy.action)
            if policy.sphere:
                print '    sphere                     = %s' % policy.sphere
            if policy.validity:
                print '    valid between:'
                for from_timestamp, until_timestamp in policy.validity:
                    print '      %s - %s' % (from_timestamp, until_timestamp)
            if policy.multi_identity_conditions:
                print '    multi identity conditions:'
                for multi_condition in policy.multi_identity_conditions:
                    if isinstance(multi_condition, CatchAllCondition) and multi_condition.exceptions:
                        print '      anyone except'
                        for exception in multi_condition.exceptions:
                            if isinstance(exception, DomainException):
                                print '        users from domain %s' % exception.domain
                            elif isinstance(exception, UserException):
                                print '        user %s' % exception.uri
                    elif isinstance(multi_condition, CatchAllCondition):
                        print '      anyone'
                    elif isinstance(multi_condition, DomainCondition) and multi_condition.exceptions:
                        print '      anyone from domain %s except' % multi_condition.domain
                        for exception in multi_condition.exceptions:
                            if isinstance(exception, UserException):
                                print '        user %s' % exception.uri
                    elif isinstance(multi_condition, DomainCondition):
                        print '      anyone from domain %s' % multi_condition.domain
            if policy.provide_devices is All:
                print '    provide-devices            = All'
            elif policy.provide_devices:
                print '    provide-devices:'
                for prv in policy.provide_devices:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    elif isinstance(prv, DeviceID):
                        print '      device-id                = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (prv, type(prv).__name__)
            if policy.provide_persons is All:
                print '    provide-persons            = All'
            elif policy.provide_persons:
                print '    provide-persons:'
                for prv in policy.provide_persons:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (prv, type(prv).__name__)
            if policy.provide_services is All:
                print '    provide-services           = All'
            elif policy.provide_services:
                print '    provide-services:'
                for prv in policy.provide_services:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    elif isinstance(prv, ServiceURI):
                        print '      service-uri              = %s' % prv
                    elif isinstance(prv, ServiceURIScheme):
                        print '      service-uri-scheme       = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (prv, type(prv).__name__)
            print '    provide-activities         = %s' % policy.provide_activities
            print '    provide-class              = %s' % policy.provide_class
            print '    provide-device-id          = %s' % policy.provide_device_id
            print '    provide-mood               = %s' % policy.provide_mood
            print '    provide-place-is           = %s' % policy.provide_place_is
            print '    provide-place-type         = %s' % policy.provide_place_type
            print '    provide-privacy            = %s' % policy.provide_privacy
            print '    provide-relationship       = %s' % policy.provide_relationship
            print '    provide-status-icon        = %s' % policy.provide_status_icon
            print '    provide-sphere             = %s' % policy.provide_sphere
            print '    provide-time-offset        = %s' % policy.provide_time_offset
            print '    provide-user-input         = %s' % policy.provide_user_input
            print '    provide-unknown-attributes = %s' % policy.provide_unknown_attributes
            print '    provide-all-attributes     = %s' % policy.provide_all_attributes
            print

        print 'Dialog-info policies:'
        for policy in notification.data.dialoginfo_policies:
            print '  %s -> %s' % (policy.id, policy.action)
            if policy.sphere:
                print '    sphere                     = %s' % policy.sphere
            if policy.validity:
                print '    valid between:'
                for from_timestamp, until_timestamp in policy.validity:
                    print '      %s - %s' % (from_timestamp, until_timestamp)
            print

        print 'RLS services:'
        for service in notification.data.services:
            print '  %s -> %s' % (service.uri, ', '.join(service.packages))
            for entry in service.entries:
                print '    %s' % entry
            print

        print 'Offline status:'
        if notification.data.offline_status:
            print '  Note: %s' % notification.data.offline_status.note
            print '  Activity: %s' % notification.data.offline_status.activity
        else:
            print '  Missing'
class XCAPApplication(object):
    __metaclass__ = Singleton
    implements(IObserver)

    def __init__(self):
        self.application = SIPApplication()
        self.xcap_manager = None

        self.quit_event = Event()

        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.application)

    def start(self):
        self.application.start(FileBackend(os.path.realpath('test-config')))

    @run_in_green_thread
    def stop(self):
        self.xcap_manager.stop()
        self.application.stop()

    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    @run_in_green_thread
    def _NH_SIPApplicationDidStart(self, notification):
        account_manager = AccountManager()
        self.xcap_manager = XCAPManager(account_manager.default_account)
        notification_center = NotificationCenter()
        notification_center.add_observer(self, sender=self.xcap_manager)
        self.xcap_manager.load(os.path.realpath('xcap-cache'))
        self.xcap_manager.start()

    def _NH_SIPApplicationDidEnd(self, notification):
        self.quit_event.set()

    def _NH_XCAPManagerDidChangeState(self, notification):
        print 'XCAP Manager state %s -> %s' % (notification.data.prev_state,
                                               notification.data.state)

    def _NH_XCAPManagerWillStart(self, notification):
        print 'XCAP Manager will start'

    def _NH_XCAPManagerDidStart(self, notification):
        print 'XCAP Manager did start'

    def _NH_XCAPManagerDidDiscoverServerCapabilities(self, notification):
        print '  contact list supported: %s' % notification.data.contactlist_supported
        print '  presence policies supported: %s' % notification.data.presence_policies_supported
        print '  dialoginfo policies supported: %s' % notification.data.dialoginfo_policies_supported
        print '  status icon supported: %s' % notification.data.status_icon_supported
        print '  offline status supported: %s' % notification.data.offline_status_supported

    def _NH_XCAPManagerWillEnd(self, notification):
        print 'XCAP Manager will end'

    def _NH_XCAPManagerDidEnd(self, notification):
        print 'XCAP Manager did end'

    def _NH_XCAPManagerDidReloadData(self, notification):
        print 'XCAP Manager reloaded data:'
        groups = dict.fromkeys(notification.data.groups)
        for group in groups:
            groups[group] = []
        for contact in notification.data.contacts:
            if contact.group is not None:
                groups[contact.group].append(contact)
        print 'Buddies:'
        for group, contacts in groups.iteritems():
            print '  %s:' % group
            for contact in contacts:
                if contact.name:
                    print '    %s <%s>' % (contact.name, contact.uri)
                else:
                    print '    %s' % contact.uri
                print '      subscribe-to-presence    = %s' % contact.subscribe_to_presence
                print '      subscribe-to-dialoginfo  = %s' % contact.subscribe_to_dialoginfo
                print '      presence-policies        = %s' % (
                    ', '.join(p.id for p in contact.presence_policies)
                    if contact.presence_policies else None)
                print '      dialoginfo-policies      = %s' % (
                    ', '.join(p.id for p in contact.dialoginfo_policies)
                    if contact.dialoginfo_policies else None)
                for attr, value in contact.attributes.iteritems():
                    print '      x: %s = %s' % (attr, value)
            print

        print 'Presence policies:'
        for policy in notification.data.presence_policies:
            print '  %s -> %s' % (policy.id, policy.action)
            if policy.sphere:
                print '    sphere                     = %s' % policy.sphere
            if policy.validity:
                print '    valid between:'
                for from_timestamp, until_timestamp in policy.validity:
                    print '      %s - %s' % (from_timestamp, until_timestamp)
            if policy.multi_identity_conditions:
                print '    multi identity conditions:'
                for multi_condition in policy.multi_identity_conditions:
                    if isinstance(
                            multi_condition,
                            CatchAllCondition) and multi_condition.exceptions:
                        print '      anyone except'
                        for exception in multi_condition.exceptions:
                            if isinstance(exception, DomainException):
                                print '        users from domain %s' % exception.domain
                            elif isinstance(exception, UserException):
                                print '        user %s' % exception.uri
                    elif isinstance(multi_condition, CatchAllCondition):
                        print '      anyone'
                    elif isinstance(
                            multi_condition,
                            DomainCondition) and multi_condition.exceptions:
                        print '      anyone from domain %s except' % multi_condition.domain
                        for exception in multi_condition.exceptions:
                            if isinstance(exception, UserException):
                                print '        user %s' % exception.uri
                    elif isinstance(multi_condition, DomainCondition):
                        print '      anyone from domain %s' % multi_condition.domain
            if policy.provide_devices is All:
                print '    provide-devices            = All'
            elif policy.provide_devices:
                print '    provide-devices:'
                for prv in policy.provide_devices:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    elif isinstance(prv, DeviceID):
                        print '      device-id                = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (
                            prv, type(prv).__name__)
            if policy.provide_persons is All:
                print '    provide-persons            = All'
            elif policy.provide_persons:
                print '    provide-persons:'
                for prv in policy.provide_persons:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (
                            prv, type(prv).__name__)
            if policy.provide_services is All:
                print '    provide-services           = All'
            elif policy.provide_services:
                print '    provide-services:'
                for prv in policy.provide_services:
                    if isinstance(prv, Class):
                        print '      class                    = %s' % prv
                    elif isinstance(prv, OccurenceID):
                        print '      occurence-id             = %s' % prv
                    elif isinstance(prv, ServiceURI):
                        print '      service-uri              = %s' % prv
                    elif isinstance(prv, ServiceURIScheme):
                        print '      service-uri-scheme       = %s' % prv
                    else:
                        print '      unknown                  = %s(%r)' % (
                            prv, type(prv).__name__)
            print '    provide-activities         = %s' % policy.provide_activities
            print '    provide-class              = %s' % policy.provide_class
            print '    provide-device-id          = %s' % policy.provide_device_id
            print '    provide-mood               = %s' % policy.provide_mood
            print '    provide-place-is           = %s' % policy.provide_place_is
            print '    provide-place-type         = %s' % policy.provide_place_type
            print '    provide-privacy            = %s' % policy.provide_privacy
            print '    provide-relationship       = %s' % policy.provide_relationship
            print '    provide-status-icon        = %s' % policy.provide_status_icon
            print '    provide-sphere             = %s' % policy.provide_sphere
            print '    provide-time-offset        = %s' % policy.provide_time_offset
            print '    provide-user-input         = %s' % policy.provide_user_input
            print '    provide-unknown-attributes = %s' % policy.provide_unknown_attributes
            print '    provide-all-attributes     = %s' % policy.provide_all_attributes
            print

        print 'Dialog-info policies:'
        for policy in notification.data.dialoginfo_policies:
            print '  %s -> %s' % (policy.id, policy.action)
            if policy.sphere:
                print '    sphere                     = %s' % policy.sphere
            if policy.validity:
                print '    valid between:'
                for from_timestamp, until_timestamp in policy.validity:
                    print '      %s - %s' % (from_timestamp, until_timestamp)
            print

        print 'RLS services:'
        for service in notification.data.services:
            print '  %s -> %s' % (service.uri, ', '.join(service.packages))
            for entry in service.entries:
                print '    %s' % entry
            print

        print 'Offline status:'
        if notification.data.offline_status:
            print '  Note: %s' % notification.data.offline_status.note
            print '  Activity: %s' % notification.data.offline_status.activity
        else:
            print '  Missing'