def _shutdown_subsystems(self): # cleanup internals if self._timer is not None and self._timer.active(): self._timer.cancel() self._timer = None # shutdown middleware components dns_manager = DNSManager() account_manager = AccountManager() addressbook_manager = AddressbookManager() session_manager = SessionManager() procs = [ proc.spawn(dns_manager.stop), proc.spawn(account_manager.stop), proc.spawn(addressbook_manager.stop), proc.spawn(session_manager.stop) ] proc.waitall(procs) # stop video device self.video_device.producer.close() # shutdown engine self.engine.stop() self.engine.join(timeout=5) # stop threads thread_manager = ThreadManager() thread_manager.stop() # stop the reactor reactor.stop()
def init(self): self._version = str( NSBundle.mainBundle().infoDictionary().objectForKey_( "CFBundleShortVersionString")) #first_start = not os.path.exists(ApplicationData.get('config')) Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(BlinkContactExtension) ContactGroup.register_extension(BlinkContactGroupExtension) SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) self._app.start(FileStorage(ApplicationData.directory)) self.init_configurations() # start session mgr SessionManager()
def init(self): if NSApp.delegate().account_extension: Account.register_extension(NSApp.delegate().account_extension) else: Account.register_extension(AccountExtension) BonjourAccount.register_extension(BonjourAccountExtension) Contact.register_extension(BlinkContactExtension) Group.register_extension(BlinkGroupExtension) ContactURI.register_extension(BlinkContactURIExtension) if NSApp.delegate().general_extension: SIPSimpleSettings.register_extension(NSApp.delegate().general_extension) else: SIPSimpleSettings.register_extension(SIPSimpleSettingsExtension) app = AppKit.NSApplication.sharedApplication() self._app.start(FileStorage(ApplicationData.directory)) # start session mgr SessionManager()
def _initialize_subsystems(self): notification_center = NotificationCenter() with self._lock: stop_pending = self._stop_pending if stop_pending: self.state = 'stopping' if stop_pending: notification_center.post_notification('SIPApplicationWillEnd', sender=self) # stop the subsystems we already started: threads, engine and reactor self.engine.stop() self.engine.join(timeout=5) thread_manager = ThreadManager() thread_manager.stop() reactor.stop() return account_manager = AccountManager() addressbook_manager = AddressbookManager() dns_manager = DNSManager() session_manager = SessionManager() settings = SIPSimpleSettings() xcap_client.DEFAULT_HEADERS = {'User-Agent': settings.user_agent} # initialize TLS self._initialize_tls() # initialize PJSIP internal resolver self.engine.set_nameservers(dns_manager.nameservers) # initialize audio objects alert_device = settings.audio.alert_device if alert_device not in ( None, 'system_default' ) and alert_device not in self.engine.output_devices: alert_device = 'system_default' input_device = settings.audio.input_device if input_device not in ( None, 'system_default' ) and input_device not in self.engine.input_devices: input_device = 'system_default' output_device = settings.audio.output_device if output_device not in ( None, 'system_default' ) and output_device not in self.engine.output_devices: output_device = 'system_default' tail_length = settings.audio.echo_canceller.tail_length if settings.audio.echo_canceller.enabled else 0 voice_mixer = AudioMixer(input_device, output_device, settings.audio.sample_rate, tail_length) voice_mixer.muted = settings.audio.muted self.voice_audio_device = AudioDevice(voice_mixer) self.voice_audio_bridge = RootAudioBridge(voice_mixer) self.voice_audio_bridge.add(self.voice_audio_device) alert_mixer = AudioMixer(None, alert_device, settings.audio.sample_rate, 0) if settings.audio.silent: alert_mixer.output_volume = 0 self.alert_audio_device = AudioDevice(alert_mixer) self.alert_audio_bridge = RootAudioBridge(alert_mixer) self.alert_audio_bridge.add(self.alert_audio_device) settings.audio.input_device = voice_mixer.input_device settings.audio.output_device = voice_mixer.output_device settings.audio.alert_device = alert_mixer.output_device # initialize video self.video_device = VideoDevice(settings.video.device, settings.video.resolution, settings.video.framerate) self.video_device.muted = settings.video.muted settings.video.device = self.video_device.name self.engine.set_video_options(settings.video.resolution, settings.video.framerate, settings.video.max_bitrate) self.engine.set_h264_options(settings.video.h264.profile, settings.video.h264.level) # initialize instance id if not settings.instance_id: settings.instance_id = uuid4().urn # initialize path for ZRTP cache file if ISIPSimpleApplicationDataStorage.providedBy(self.storage): self.engine.zrtp_cache = os.path.join(self.storage.directory, 'zrtp.db') # save settings in case something was modified during startup settings.save() # initialize middleware components dns_manager.start() account_manager.start() addressbook_manager.start() session_manager.start() notification_center.add_observer(self, name='CFGSettingsObjectDidChange') notification_center.add_observer(self, name='DNSNameserversDidChange') notification_center.add_observer(self, name='SystemIPAddressDidChange') notification_center.add_observer(self, name='SystemDidWakeUpFromSleep') with self._lock: self.state = 'started' stop_pending = self._stop_pending notification_center.post_notification('SIPApplicationDidStart', sender=self) if stop_pending: self.stop()
def _addIncomingSession(self, session, streams, is_update_proposal): view = self.getItemView() self.sessions[session] = view settings = SIPSimpleSettings() stream_type_list = list(set(stream.type for stream in streams)) if len(self.sessions) == 1: self.panel.setTitle_(u"Incoming Call from %s" % format_identity_to_string(session.remote_identity, check_contact=True, format='compact')) if settings.sounds.enable_speech_synthesizer: if stream_type_list == ["chat"]: base_text = "Chat from %s" else: base_text = "Call from %s" self.speak_text = base_text % format_identity_to_string(session.remote_identity, check_contact=True, format='compact') self.startSpeechSynthesizerTimer() else: self.panel.setTitle_(u"Multiple Incoming Calls") NotificationCenter().add_observer(self, sender=session) captionT = view.viewWithTag_(1) fromT = view.viewWithTag_(2) destT = view.viewWithTag_(3) acceptB = view.viewWithTag_(5) rejectB = view.viewWithTag_(7) otherB = view.viewWithTag_(6) busyB = view.viewWithTag_(8) photoImage = view.viewWithTag_(99) stream_types = [s.type for s in streams] session_manager = SessionManager() have_audio_call = any(s for s in session_manager.sessions if s is not session and s.streams and 'audio' in (stream.type for stream in s.streams)) if not have_audio_call: self.startSpeechRecognition() typeCount = 0 if 'audio' in stream_types: audioIcon = view.viewWithTag_(32) frame = audioIcon.frame() typeCount+= 1 frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount audioIcon.setFrame_(frame) audioIcon.setHidden_(False) if not is_update_proposal: frame = view.frame() frame.size.height += 20 # give extra space for the counter label view.setFrame_(frame) if session.account.audio.auto_accept: have_audio_call = any(s for s in session_manager.sessions if s is not session and s.streams and 'audio' in (stream.type for stream in s.streams)) if not have_audio_call: self.enableAutoAnswer(view, session) elif SIPSimpleSettings().answering_machine.enabled: self.enableAnsweringMachine(view, session) if 'chat' in stream_types: chatIcon = view.viewWithTag_(31) frame = chatIcon.frame() typeCount+= 1 frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount chatIcon.setFrame_(frame) chatIcon.setHidden_(False) if 'desktop-sharing' in stream_types: desktopIcon = view.viewWithTag_(34) frame = desktopIcon.frame() typeCount+= 1 frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount desktopIcon.setFrame_(frame) desktopIcon.setHidden_(False) is_file_transfer = False if 'file-transfer' in stream_types: is_file_transfer = True fileIcon = view.viewWithTag_(33) frame = fileIcon.frame() typeCount+= 1 frame.origin.x = NSMaxX(view.frame()) - 10 - (NSWidth(frame) + 10) * typeCount fileIcon.setFrame_(frame) fileIcon.setHidden_(False) self.sessionsListView.addSubview_(view) frame = self.sessionsListView.frame() frame.origin.y = self.extraHeight - 14 frame.size.height = self.sessionsListView.minimumHeight() self.sessionsListView.setFrame_(frame) height = frame.size.height + self.extraHeight size = NSMakeSize(NSWidth(self.panel.frame()), height) screenSize = NSScreen.mainScreen().frame().size if size.height > (screenSize.height * 2) / 3: size.height = (screenSize.height * 2) / 3 frame = self.panel.frame() frame.size.height = size.height frame.size.height = NSHeight(self.panel.frameRectForContentRect_(frame)) self.panel.setFrame_display_animate_(frame, True, True) self.sessionsListView.relayout() acceptB.cell().setRepresentedObject_(NSNumber.numberWithInt_(0)) otherB.cell().setRepresentedObject_(NSNumber.numberWithInt_(1)) rejectB.cell().setRepresentedObject_(NSNumber.numberWithInt_(2)) busyB.cell().setRepresentedObject_(NSNumber.numberWithInt_(3)) # no Busy or partial accept option for Stream Update Proposals busyB.setHidden_(is_update_proposal or is_file_transfer) otherB.setHidden_(is_update_proposal) if is_file_transfer: busyB.setAttributedTitle_("") panelAcceptB = self.panel.contentView().viewWithTag_(10) panelOtherB = self.panel.contentView().viewWithTag_(11) panelRejectB = self.panel.contentView().viewWithTag_(12) panelBusyB = self.panel.contentView().viewWithTag_(13) if is_update_proposal: subject, accept, other = self.format_subject_for_incoming_reinvite(session, streams) other = "" else: subject, accept, other = self.format_subject_for_incoming_invite(session, streams) captionT.setStringValue_(subject) frame = captionT.frame() frame.size.width = NSWidth(self.sessionsListView.frame()) - 80 - 40 * typeCount captionT.setFrame_(frame) caller_contact = NSApp.delegate().contactsWindowController.getContactMatchingURI(session.remote_identity.uri) if caller_contact: if caller_contact.icon: photoImage.setImage_(caller_contact.icon) if caller_contact.auto_answer: BlinkLogger().log_info(u"Auto answer enabled for this contact") self.enableAutoAnswer(view, session) fromT.setStringValue_(u"%s" % format_identity_to_string(session.remote_identity, check_contact=True, format='full')) fromT.sizeToFit() has_audio_streams = any(s for s in reduce(lambda a,b:a+b, [session.proposed_streams for session in self.sessions.keys()], []) if s.type=="audio") if has_audio_streams: outdev = SIPSimpleSettings().audio.output_device indev = SIPSimpleSettings().audio.input_device if outdev == u"system_default": outdev = u"System Default" if indev == u"system_default": indev = u"System Default" if outdev != indev: self.deviceLabel.setStringValue_(u"Selected Output Device is %s, Input is %s" % (outdev.strip(), indev.strip())) else: self.deviceLabel.setStringValue_(u"Selected Audio Device is %s" % outdev.strip()) BlinkLogger().log_info(u"Selected audio input/output devices: %s/%s" % (indev, outdev)) self.deviceLabel.sizeToFit() self.deviceLabel.setHidden_(False) else: self.deviceLabel.setHidden_(True) acceptB.setTitle_(accept or "") otherB.setTitle_(other or "") if False and sum(a.enabled for a in AccountManager().iter_accounts())==1: destT.setHidden_(True) else: destT.setHidden_(False) if isinstance(session.account, BonjourAccount): destT.setStringValue_(u"To Bonjour account") else: destT.setStringValue_(u"To %s" % format_identity_to_string(session.account)) destT.sizeToFit() if len(self.sessions) == 1: panelAcceptB.setTitle_(accept) panelAcceptB.setHidden_(False) panelOtherB.setTitle_(other or "") panelOtherB.setHidden_(not other) panelRejectB.setTitle_("Reject") panelAcceptB.cell().setRepresentedObject_(NSNumber.numberWithInt_(0)) panelRejectB.cell().setRepresentedObject_(NSNumber.numberWithInt_(2)) panelBusyB.cell().setRepresentedObject_(NSNumber.numberWithInt_(3)) panelOtherB.cell().setRepresentedObject_(NSNumber.numberWithInt_(1)) panelBusyB.setHidden_(is_update_proposal or is_file_transfer) for i in (5, 6, 7, 8): view.viewWithTag_(i).setHidden_(True) else: panelAcceptB.setHidden_(False) panelAcceptB.setTitle_("Accept All") panelOtherB.setHidden_(True) panelBusyB.setHidden_(is_update_proposal or is_file_transfer) panelRejectB.setTitle_("Reject All") for v in self.sessions.values(): for i in (5, 6, 7, 8): btn = v.viewWithTag_(i) btn.setHidden_(len(btn.attributedTitle()) == 0)