class MainWindow(wx.Frame): acc=None call=None tbUser=None userDao=None # tbConfig=None configDao=None voiceCallBtn=None videoCallBtn=None callUserText=None notebookPanel=None taskBar=None lastErrorInfo="" _previousSize=None _previousPos=None ### for force disconnected,but actually not disconnected _listCallInfo=[] def on_reg_state(self,evt): reg_status= evt.GetValue() if reg_status == 200: self.SetTitle(_("register OK")) self.taskBar.setRegisted(True) else: self.SetTitle(_("register failed")+":"+str(reg_status)) self.taskBar.setRegisted(False) def make_call(self,vidCnt=1): if len(self._listCallInfo) > 0: user = self.callUserText.GetValue().strip() uri="sip:"+user+"@"+self.tbUser.domain for getInfo in self._listCallInfo: if getInfo.remote_uri == uri: self.showMessage(_("call_already_exist_please_wait")) return if not self.call and self.acc: user = self.callUserText.GetValue().strip() uri="sip:"+user+"@"+self.tbUser.domain if self.tbUser.name == user: self.showMessage(_("can't call myself")) return try: self.call = self.acc.make_call(str(uri),cb=MyUtil.MyCallCallback(self),vid_cnt=vidCnt) self._listCallInfo.append(self.call.info()) ### setup notebook's ui self.notebookPanel.call_on_state(self.call,0,None) self.configDao.SetLastCallNum(user) self.configDao.commitSession() except : self.show_err_msg() def on_incoming_call(self,evt): call = evt.GetValue() if (self.call) or len(self._listCallInfo) > 0: call.answer(486) return call.answer(180) call.set_callback(MyUtil.MyCallCallback(self,isIncomingCall=True)) self.call=call self._listCallInfo.append(self.call.info()) self.taskBar.on_incoming_call(True) self.notebookPanel.on_incoming_call(call) def on_state(self,evt): # call = evt.GetValue() # info = call.info() info = evt.GetValue() code = int(info.last_code) state = info.state_text if (state == "DISCONNCTD"): for getInfo in self._listCallInfo: if getInfo.sip_call_id == info.sip_call_id: self._listCallInfo.remove(getInfo) self.real_on_state(code,state) def real_on_state(self,code,state): if not self.call: return ### http://www.51testing.com/html/90/360490-834635.html ### 404 not found,408 Request Timeout,480 temporary unavailable,486 Busy,487 500 Internal Server Err,timeout,603 decline if state=="DISCONNCTD" or state == "immediately": # self.call.attach_to_id(-1) self.call = None ### notebookPanel UI set self.notebookPanel.call_on_state(self.call,code,state) self.taskBar.on_incoming_call(False) def on_media_state(self,evt): info = evt.GetValue() if info.media_state == pj.MediaState.ACTIVE and self.call.vid_win_id(): self.notebookPanel.on_media_sate(self.call.vid_win_id()) def showMessage(self,msg,title=""): wx.MessageBox(msg,title) def __setUi(self): self.Bind(wx.EVT_CLOSE, self.__OnCloseWindow) self.Bind( MyUtil.EVT_ON_INCOMING_CALL,self.on_incoming_call) self.Bind(MyUtil.EVT_ON_REG_STATE,self.on_reg_state) self.Bind(MyUtil.EVT_ON_STATE,self.on_state) self.Bind(MyUtil.EVT_ON_MEDIA_STATE,self.on_media_state) # option menu optionmenu= wx.Menu() sipConfigMenuItem = optionmenu.Append(101,_("&Sip Config"),"") natTravelMenuItem = optionmenu.Append(102,_("&Nat Traversal"),"") otherConfigMenuItem = optionmenu.Append(103,_("&Other Config"),"") self.Bind(wx.EVT_MENU, self.doSipConfigMenuItem, sipConfigMenuItem) self.Bind(wx.EVT_MENU, self.doNatTravelConfig, natTravelMenuItem) self.Bind(wx.EVT_MENU, self.doOtherConfig, otherConfigMenuItem) menuBar = wx.MenuBar() menuBar.Append(optionmenu,(_("&Option"))) self.SetMenuBar(menuBar) panel = wx.Panel(self,-1) panel.SetAutoLayout(True) #### topPanel layout topPanel = wx.Window(panel,-1,style=wx.NO_BORDER) topPanel.SetConstraints(layoutf.Layoutf('t=t10#1;l=l10#1;b=b10#1;r=r10#1;h!40',(panel,))) box = wx.BoxSizer(wx.HORIZONTAL) box.Add( wx.StaticText(topPanel, -1, _("sip")+":"), 0, wx.ALIGN_CENTER) self.callUserText=text=wx.TextCtrl(topPanel, -1, self.configDao.GetLastCallNum(),style=wx.TE_PROCESS_ENTER) self.Bind(wx.EVT_TEXT_ENTER, self.onCallUserTextEnter, text) box.Add(text, 1, wx.ALIGN_CENTER) self.videoCallBtn =btn=wx.Button(topPanel, -1, _('call')) self.Bind(wx.EVT_BUTTON, self.onVideoCallBtnClick, btn) box.Add(btn, 0,wx.ALIGN_CENTER) self.voiceCallBtn = btn = wx.Button(topPanel, -1, _('no video call')) self.Bind(wx.EVT_BUTTON, self.onVoiceCallBtnClick, btn) box.Add(btn, 0,wx.ALIGN_CENTER) topPanel.SetSizer(box) ### center panel layout centerPanel = wx.Window(panel,-1,style=wx.NO_BORDER) # centerPanel.SetBackgroundColour(wx.RED) centerPanel.SetConstraints(layoutf.Layoutf('t=t45#2;l=l10#1;b=b10#1;r=r10#1',(panel,topPanel))) self.notebookPanel=notebook=MyWidget.MainNoteBookPanel(centerPanel,-1,self) notebook.SetConstraints(layoutf.Layoutf('t=t0#1;l=l0#1;b=b0#1;r=r0#1',(centerPanel,))) ### debug # notebook.on_incoming_call(None) ### system tray self.taskBar=MyWidget.TaskBarIcon(self) def __startSipLib(self): isSuccess = True global lib if lib: self.__stopSipLib() lib = pj.Lib() self._listCallInfo=[] try: # if True: dao = self.configDao; mediaConfig=MediaConfig() mediaConfig.enable_ice = MyUtil.db_str2bool(dao.GetIsUseIce()) mediaConfig.enable_turn =MyUtil.db_str2bool(dao.GetIsUseTurn()) if mediaConfig.enable_turn: mediaConfig.turn_server = str(dao.GetTurnServer()) uaConfig=UAConfig() if (MyUtil.db_str2bool(dao.GetIsUseStun())): uaConfig.stun_srv = [str(dao.GetStunServer())] lib.init(ua_cfg = uaConfig,log_cfg = pj.LogConfig(level=int(dao.GetLogLevel()), callback=self.log_cb), media_cfg=mediaConfig) lib.create_transport(pj.TransportType.UDP, pj.TransportConfig(int(dao.GetSipSendPort()))) lib.start() except: isSuccess=False self.show_err_msg() if isSuccess: isSuccess=self.reRegister() return isSuccess def __stopSipLib(self): global lib if self.call: self.call.attach_to_id(-1) self.call=None if self.acc: self.acc.delete() self.acc =None if lib: lib.destroy() lib = None def __init__(self, parent, title): startDlg = MyWidget.StartUpProgressBar() ## dao init startDlg.update(5,_("initial database")) self.userDao = TbUser() self.configDao =TbConfig() startDlg.update(15,_("initial parent window")) wx.Frame.__init__(self, parent, title=title,size=(int(self.configDao.GetWinW()),int(self.configDao.GetWinH())),pos=(int(self.configDao.GetWinX()),int(self.configDao.GetWinY()))) startDlg.update(35,_("initial UI")) self.__setUi() ### lib init this may delay several seconds startDlg.update(65,_("initial sip lib")) self.__startSipLib() if (self.userDao.getCount() == 0): startDlg.update(100) self.doSipConfigMenuItem(None) startDlg.update(100) startDlg.Destroy() self.Raise() self.Show(True) self._previousSize = self.GetSize() self._previousPos = self.GetPosition() def onCallUserTextEnter(self,event): if (self.callUserText.GetValue()): self.onVideoCallBtnClick(None) event.Skip() def onVideoCallBtnClick(self,e): self.__onCallBtnClick(1) def onVoiceCallBtnClick(self,e): self.__onCallBtnClick(0) def __onCallBtnClick(self,vidCnt=1): self.make_call(vidCnt) def doSipConfigMenuItem(self,e): dlg = MyWidget.SipConfigDialog(self, -1, _("sip config window")) if self.tbUser: dlg.setValue(self.tbUser.domain, self.tbUser.name, self.tbUser.pwd) dlg.CenterOnScreen() if not self.IsShown(): dlg.Raise() # this does not return until the dialog is closed. val = dlg.ShowModal() if val == wx.ID_OK: if not self.tbUser: self.tbUser =TbUser() self.tbUser.domain=dlg.domainText.GetValue() self.tbUser.name=dlg.userText.GetValue() self.tbUser.pwd=dlg.pwdText.GetValue() self.userDao.addUser(self.tbUser) if self.reRegister(): self.userDao.commitSession() else: self.userDao.rollbackSession() dlg.Destroy() # self.acc.info().media_state # win32gui.SetParent(self.call.vid_win_id(),self.Handle) def doNatTravelConfig(self,e): dlg = MyWidget.NetTraversalConfigDialog(self, -1, _("nat traversal config")) dao = self.configDao dlg.setValue(dao.GetIsUseIce(),dao.GetIsUseStun(),dao.GetStunServer(),dao.GetIsUseTurn(),dao.GetTurnServer()) # this does not return until the dialog is closed. dlg.CenterOnScreen() val = dlg.ShowModal() if val == wx.ID_OK: dao.SetIsUseIce(MyUtil.db_bool2str(dlg.useIce.GetValue())) dao.SetIsUseStun(MyUtil.db_bool2str(dlg.useStun.GetValue())) dao.SetIsUseTurn(MyUtil.db_bool2str(dlg.useTurn.GetValue())) dao.SetStunServer(dlg.stunServer.GetValue()) dao.SetTurnServer(dlg.turnServer.GetValue()) if self.__startSipLib(): dao.commitSession() else: dao.rollbackSession() dlg.Destroy() def doOtherConfig(self,e): dlg = MyWidget.OtherConfigDialog(self, -1, _("other config")) dao = self.configDao dlg.setValue(dao.GetSipSendPort(),dao.GetLogLevel()) # this does not return until the dialog is closed. dlg.CenterOnScreen() val = dlg.ShowModal() if val == wx.ID_OK: dao.SetSipSendPort(dlg.sipPort.GetValue()) dao.SetLogLevel(dlg.logLevel.GetValue()) if self.__startSipLib(): dao.commitSession() else: dao.rollbackSession() dlg.Destroy() def reRegister(self): return self.__reSetAccount() def __reSetAccount(self): isSucess=True if self.acc: self.acc.delete() self.acc =None if self.userDao.getCount() > 0: self.tbUser= self.userDao.getFirstUser() account = pj.AccountConfig(str(self.tbUser.domain), str(self.tbUser.name), str(self.tbUser.pwd)) # account.reg_timeout =30 try: self.acc = lib.create_account(account) acc_cb = MyUtil.MyAccountCallback(self.acc,self) self.acc.set_callback(acc_cb) acc_cb.wait() self.SetTitle(_("on registing")+"...") self.taskBar.startRegistingBlink() except: isSucess=False self.show_err_msg() # else: # self.SetTitle(_("no account")) return isSucess def __OnCloseWindow(self,event): self.__saveWinData() self.Show(False) def OnCloseWindow(self): self.__saveWinData() self.__stopSipLib() self.Destroy() def __saveWinData(self): isNeedUpdate=None if (self._previousSize != self.GetSize()): w,h=self._previousSize = self.GetSize() self.configDao.SetWinW(w) self.configDao.SetWinH(h) isNeedUpdate = True if (self._previousPos != self.GetPosition()): x,y=self._previousPos = self.GetPosition(); self.configDao.SetWinX(x) self.configDao.SetWinY(y) isNeedUpdate = True if (isNeedUpdate): self.configDao.commitSession() def log_cb(self,level, str2, len): if (level==1): MyUtil.saveErrorLog(str2) self.lastErrorInfo += str(str2) ### this is the err can't be caught by the program if (level ==1): if "[status=370004]" in str2: self.show_err_msg() print str2 def show_err_msg(self): dlg = wx.MessageDialog(self,MyUtil.ProcessErrMsg(self.lastErrorInfo) , _('Err Message'), wx.OK | wx.ICON_ERROR #wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION ) self.lastErrorInfo ="" dlg.ShowModal() dlg.Destroy()