class Application: """ The Application main entry """ def __init__(self, argv): logger = Logger().logger self.appConfig = AppConfig(logger) self.logger = logger self.quitting = False self.handling_events = False self.accounts = {} self.logger.debug("Creating the Endpoint") self.endpoint = Endpoint(self) def start(self): self.logger.debug("starting up") self.endpoint.libCreate() self.endpoint.libInit(self.appConfig.epConfig) self.logger.debug("lib initialized") self.endpoint.transportCreate(self.appConfig.udp.type, self.appConfig.udp.config) self.logger.debug("transport created") self.endpoint.libStart() self.logger.debug("lib started") for account in self.appConfig.accounts: if account.enabled: self._createAccount(account.config) def _createAccount(self, config): self.logger.debug("creating account '{}'".format(config.idUri)) account = Account(self, config) account.create(account.config) self.accounts[config.idUri] = account self.logger.debug("created account '{}'".format(config.idUri)) def onSelectAccount(self, param): """ params is: SipRxData rdata The incoming request. int accountIndex Upon entry, this will be filled by the account index chosen by the library. Application may change it to another value to use another account. SipRxData is: string info A short info string describing the request, which normally contains the request method and its CSeq. string wholeMsg The whole message data as a string, containing both the header section and message body section. SocketAddress srcAddress Source address of the message. (This is a string containing "host[:port]") """ self.logger.debug("recieved msg {} for {}".format( param.rdata.info, param.accountIndex)) return 0 def make_call(self): while True and not self.quitting: self.logger.debug("handling events") self.handling_events = True self.endpoint.libHandleEvents(10) self.handling_events = False self.logger.debug("finished handling events") time.sleep(.50) self.logger.debug("pretending making call") def os_signal_handler(self, signal, frame): self.shutdown() def shutdown(self): self.quitting = True self.logger.debug("shutting down") self.endpoint.libDestroy()
class Main(tk.Tk): def __init__(self): super().__init__() """ Initialize PJSUA2 """ self.ep = Endpoint() self.ep.libCreate() self.ep_cfg = pj.EpConfig() # self.ep_cfg.uaConfig.threadCnt = 0 # self.ep_cfg.uaConfig.mainThreadOnly = True self.ep_cfg.logConfig.level = 1 self.ep.libInit(self.ep_cfg) self.ts_cfg = pj.TransportConfig() self.ep.transportCreate(pj.PJSIP_TRANSPORT_UDP, self.ts_cfg) self.ep.libStart() """ Initialize Account """ self.acc = None self.domain = DEFAULT_DOMAIN self.buddy_list = {} self.chat_list = {} """ Initialize UI """ self.title('SIP Client') self.resizable(width=False, height=False) self.geometry('+{}+{}'.format(int(self.winfo_screenwidth() / 2), int(self.winfo_screenheight() / 2))) self.buddy = tk.Entry(self, font=FONT_CONTENT, width=30) self.buddy.grid(row=0, column=0, columnspan=3, padx=10, pady=10) self.buddy.bind('<Return>', self._add_buddy) self.buddy_view = ttk.Treeview(self, column=['1', '2'], show='headings', selectmode='browse') self.buddy_view.column('1', width=80, anchor='center') self.buddy_view.column('2', width=200, anchor='center') self.buddy_view.heading('1', text='Buddies') self.buddy_view.heading('2', text='Status') self.buddy_view.grid(row=1, column=0, columnspan=3, padx=10, pady=10) self.buddy_view.bind('<Double-Button-1>', self._create_chat) self.buddy_view.bind('<BackSpace>', self._delete_buddy) tk.Button(self, text='Logout', font=FONT_CONTENT, width=8, command=self._login).grid(row=2, column=0, padx=10, pady=10) tk.Button(self, text='Exit', font=FONT_CONTENT, width=8, command=self._exit).grid(row=2, column=2, padx=10, pady=10) self._login() # self._on_timer() self.mainloop() def _add_buddy(self, event): iid = self.buddy.get() if iid not in self.buddy_list: # Initialize buddy bud = Buddy(self, iid) # Initialize configuration of buddy bud_cfg = pj.BuddyConfig() bud_cfg.uri = 'sip:' + iid + '@' + self.domain # Create buddy bud.cfg = bud_cfg bud.create(self.acc, bud.cfg) bud.subscribePresence(True) # Push into buddy_list self.buddy_list[iid] = bud self.update_buddy(bud) self.buddy.delete(0, 'end') def _delete_buddy(self, event): for key in self.buddy_view.selection(): self.buddy_view.delete(key) self.buddy_list.pop(key) def update_buddy(self, bud): iid = bud.iid if iid in self.buddy_list: self.buddy_view.item(iid, value=(iid, bud.status())) else: self.buddy_view.insert('', 'end', iid=iid, values=(iid, bud.status())) def update_account(self): # TODO() print(self.acc.status()) def incoming_call(self, prm): call = Call(self.acc, call_id=prm.callId) call_prm = pj.CallOpParam() # Ringing State call_prm.statusCode = pj.PJSIP_SC_RINGING call.answer(call_prm) # Set uri call.uri = call.getInfo().remoteUri iid = call.uri.split(':')[1].split('@')[0] if msg.askquestion('Incoming Call', 'Accept call from ' + iid + ' ?', default=msg.YES): # If not exist current buddy, then create if iid not in self.buddy_list: # Initialize buddy bud = Buddy(self, iid) # Initialize configuration of buddy bud_cfg = pj.BuddyConfig() bud_cfg.uri = 'sip:' + iid + '@' + self.domain # Create buddy bud.cfg = bud_cfg bud.create(self.acc, bud.cfg) bud.subscribePresence(True) # Push into buddy_list self.buddy_list[iid] = bud self.update_buddy(bud) # If not exist current chat dialog, then create if iid not in self.chat_list: self.chat_list[iid] = Chat(self.acc, self.buddy_list[iid], self) # Inform the corresponding chat self.chat_list[iid].receive_call(call) else: call.hangup(call_prm) def instant_message(self, uri, msg): iid = uri[1:-1].split(':')[1].split('@')[0] if iid in self.chat_list: self.chat_list[iid].receive_message(msg) else: pass def _create_chat(self, event): for iid in self.buddy_view.selection(): self.chat_list[iid] = Chat(self.acc, self.buddy_list[iid], self) def delete_chat(self, iid): self.chat_list.pop(iid) def _login(self): # Initialize configuration of account acc_cfg = pj.AccountConfig() # Create LoginDialog dlg = Login(self, acc_cfg) # Wait for response if dlg.do_modal(): # Initialize account self.acc = Account(self) # Set configuration self.acc.cfg = acc_cfg self.acc.create(self.acc.cfg) # Set online status ps = pj.PresenceStatus() ps.status = pj.PJSUA_BUDDY_STATUS_ONLINE self.acc.setOnlineStatus(ps) # Update title self.title(self.acc.cfg.idUri) # Get the uri of server self.domain = self.acc.cfg.regConfig.registrarUri.split(':')[1] # Reset all self.buddy_list = {} self.chat_list = {} for key in self.buddy_view.get_children(): self.buddy_view.delete(key) # If never login if not self.acc: # Then exit self._exit() def _exit(self): self.ep.libDestroy() self.ep = None self.destroy()