Ignore:
Timestamp:
Aug 2, 2017 9:45:09 AM (5 years ago)
Author:
riza
Message:

Close #2034: Add support to Python3 using PJSUA2 API.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pygui/account.py

    r4704 r5638  
    2121import sys 
    2222if sys.version_info[0] >= 3: # Python 3 
    23         import tkinter as tk 
    24         from tkinter import ttk 
    25         from tkinter import messagebox as msgbox 
     23    import tkinter as tk 
     24    from tkinter import ttk 
     25    from tkinter import messagebox as msgbox 
    2626else: 
    27         import Tkinter as tk 
    28         import tkMessageBox as msgbox 
    29         import ttk 
     27    import Tkinter as tk 
     28    import tkMessageBox as msgbox 
     29    import ttk 
    3030 
    3131import random 
     
    3737import chat as ch 
    3838 
     39write=sys.stdout.write 
     40 
    3941# Account class 
    4042class Account(pj.Account): 
    41         """ 
    42         High level Python Account object, derived from pjsua2's Account object. 
    43         """ 
    44         def __init__(self, app): 
    45                 pj.Account.__init__(self) 
    46                 self.app = app 
    47                 self.randId = random.randint(1, 9999) 
    48                 self.cfg =  pj.AccountConfig() 
    49                 self.cfgChanged = False 
    50                 self.buddyList = [] 
    51                 self.chatList = [] 
    52                 self.deleting = False 
    53  
    54         def findChat(self, uri_str): 
    55                 uri = ch.ParseSipUri(uri_str) 
    56                 if not uri: return None 
    57                          
    58                 for chat in self.chatList: 
    59                         if chat.isUriParticipant(uri) and chat.isPrivate(): 
    60                                 return chat 
    61                 return None 
    62          
    63         def newChat(self, uri_str): 
    64                 uri = ch.ParseSipUri(uri_str) 
    65                 if not uri: return None 
    66                          
    67                 chat = ch.Chat(self.app, self, uri) 
    68                 self.chatList.append(chat) 
    69                 self.app.updateWindowMenu() 
    70                 return chat 
    71          
    72         def statusText(self): 
    73                 status = '?' 
    74                 if self.isValid(): 
    75                         ai = self.getInfo() 
    76                         if ai.regLastErr: 
    77                                 status = self.app.ep.utilStrError(ai.regLastErr) 
    78                         elif ai.regIsActive: 
    79                                 if ai.onlineStatus: 
    80                                         if len(ai.onlineStatusText): 
    81                                                 status = ai.onlineStatusText 
    82                                         else: 
    83                                                 status = "Online" 
    84                                 else: 
    85                                         status = "Registered" 
    86                         else: 
    87                                 if ai.regIsConfigured: 
    88                                         if ai.regStatus/100 == 2: 
    89                                                 status = "Unregistered" 
    90                                         else: 
    91                                                 status = ai.regStatusText 
    92                                 else: 
    93                                         status = "Doesn't register" 
    94                 else: 
    95                         status = '- not created -' 
    96                 return status 
    97                  
    98         def onRegState(self, prm): 
    99                 self.app.updateAccount(self) 
    100  
    101         def onIncomingCall(self, prm): 
    102                 c = call.Call(self, call_id=prm.callId) 
    103                 call_prm = pj.CallOpParam() 
    104                 call_prm.statusCode = 180 
    105                 c.answer(call_prm) 
    106                 ci = c.getInfo() 
    107                 msg = "Incoming call for account '%s'" % self.cfg.idUri 
    108                 if msgbox.askquestion(msg, "Accept call from '%s'?" % (ci.remoteUri), default=msgbox.YES) == u'yes': 
    109                         call_prm.statusCode = 200 
    110                         c.answer(call_prm) 
    111                          
    112                         # find/create chat instance 
    113                         chat = self.findChat(ci.remoteUri) 
    114                         if not chat: chat = self.newChat(ci.remoteUri) 
    115                          
    116                         chat.showWindow() 
    117                         chat.registerCall(ci.remoteUri, c) 
    118                         chat.updateCallState(c, ci) 
    119                 else: 
    120                         c.hangup(call_prm) 
    121                          
    122         def onInstantMessage(self, prm): 
    123                 chat = self.findChat(prm.fromUri) 
    124                 if not chat: chat = self.newChat(prm.fromUri) 
    125                  
    126                 chat.showWindow() 
    127                 chat.addMessage(prm.fromUri, prm.msgBody) 
    128                  
    129         def onInstantMessageStatus(self, prm): 
    130                 if prm.code/100 == 2: return 
    131                  
    132                 chat = self.findChat(prm.toUri) 
    133                 if not chat: 
    134                         print "=== IM status to '%s' cannot find chat" % prm.toUri 
    135                         return 
    136                  
    137                 chat.addMessage(None, "Failed sending message to '%s': %s" % (prm.toUri, prm.reason)) 
    138                  
    139         def onTypingIndication(self, prm): 
    140                 chat = self.findChat(prm.fromUri) 
    141                 if not chat: 
    142                         print "=== Incoming typing indication from '%s' cannot find chat" % prm.fromUri 
    143                         return 
    144                  
    145                 chat.setTypingIndication(prm.fromUri, prm.isTyping) 
    146  
    147                  
     43    """ 
     44    High level Python Account object, derived from pjsua2's Account object. 
     45    """ 
     46    def __init__(self, app): 
     47        pj.Account.__init__(self) 
     48        self.app = app 
     49        self.randId = random.randint(1, 9999) 
     50        self.cfg =  pj.AccountConfig() 
     51        self.cfgChanged = False 
     52        self.buddyList = [] 
     53        self.chatList = [] 
     54        self.deleting = False 
     55 
     56    def findChat(self, uri_str): 
     57        uri = ch.ParseSipUri(uri_str) 
     58        if not uri: return None 
     59 
     60        for chat in self.chatList: 
     61            if chat.isUriParticipant(uri) and chat.isPrivate(): 
     62                return chat 
     63        return None 
     64 
     65    def newChat(self, uri_str): 
     66        uri = ch.ParseSipUri(uri_str) 
     67        if not uri: return None 
     68 
     69        chat = ch.Chat(self.app, self, uri) 
     70        self.chatList.append(chat) 
     71        self.app.updateWindowMenu() 
     72        return chat 
     73 
     74    def statusText(self): 
     75        status = '?' 
     76        if self.isValid(): 
     77            ai = self.getInfo() 
     78            if ai.regLastErr: 
     79                status = self.app.ep.utilStrError(ai.regLastErr) 
     80            elif ai.regIsActive: 
     81                if ai.onlineStatus: 
     82                    if len(ai.onlineStatusText): 
     83                        status = ai.onlineStatusText 
     84                    else: 
     85                        status = "Online" 
     86                else: 
     87                    status = "Registered" 
     88            else: 
     89                if ai.regIsConfigured: 
     90                    if ai.regStatus/100 == 2: 
     91                        status = "Unregistered" 
     92                    else: 
     93                        status = ai.regStatusText 
     94                else: 
     95                    status = "Doesn't register" 
     96        else: 
     97            status = '- not created -' 
     98        return status 
     99 
     100    def onRegState(self, prm): 
     101        self.app.updateAccount(self) 
     102 
     103    def onIncomingCall(self, prm): 
     104        c = call.Call(self, call_id=prm.callId) 
     105        call_prm = pj.CallOpParam() 
     106        call_prm.statusCode = 180 
     107        c.answer(call_prm) 
     108        ci = c.getInfo() 
     109        msg = "Incoming call for account '%s'" % self.cfg.idUri 
     110        if msgbox.askquestion(msg, "Accept call from '%s'?" % (ci.remoteUri), default=msgbox.YES) == u'yes': 
     111            call_prm.statusCode = 200 
     112            c.answer(call_prm) 
     113 
     114            # find/create chat instance 
     115            chat = self.findChat(ci.remoteUri) 
     116            if not chat: chat = self.newChat(ci.remoteUri) 
     117 
     118            chat.showWindow() 
     119            chat.registerCall(ci.remoteUri, c) 
     120            chat.updateCallState(c, ci) 
     121        else: 
     122            c.hangup(call_prm) 
     123 
     124    def onInstantMessage(self, prm): 
     125        chat = self.findChat(prm.fromUri) 
     126        if not chat: chat = self.newChat(prm.fromUri) 
     127 
     128        chat.showWindow() 
     129        chat.addMessage(prm.fromUri, prm.msgBody) 
     130 
     131    def onInstantMessageStatus(self, prm): 
     132        if prm.code/100 == 2: return 
     133 
     134        chat = self.findChat(prm.toUri) 
     135        if not chat: 
     136            write("=== IM status to " + prm.toUri + "cannot find chat\r\n") 
     137            return 
     138 
     139        chat.addMessage(None, "Failed sending message to '%s': %s" % (prm.toUri, prm.reason)) 
     140 
     141    def onTypingIndication(self, prm): 
     142        chat = self.findChat(prm.fromUri) 
     143        if not chat: 
     144            write("=== Incoming typing indication from " + prm.fromUri + "cannot find chat\r\n") 
     145            return 
     146 
     147        chat.setTypingIndication(prm.fromUri, prm.isTyping) 
     148 
     149 
    148150# Account frame, to list accounts 
    149151class AccountListFrame(ttk.Frame): 
    150         """ 
    151         This implements a Frame which contains account list and buttons to operate 
    152         on them (Add, Modify, Delete, etc.).  
    153         """ 
    154         def __init__(self, parent, app, acc_list = []): 
    155                 ttk.Frame.__init__(self, parent, name='acclist') 
    156                 self.app = app 
    157                 self.accList = acc_list 
    158                 self.accDeletedList = [] 
    159                 self.pack(expand='yes', fill='both') 
    160                 self._createWidgets() 
    161                 for acc in self.accList: 
    162                         self._showAcc(acc) 
    163                  
    164         def _createWidgets(self): 
    165                 self.tv = ttk.Treeview(self, columns=('ID', 'Registrar', 'Default'), selectmode='browse') 
    166                 self.tv.heading('#0', text='Priority') 
    167                 self.tv.heading(0, text='ID') 
    168                 self.tv.heading(1, text='Registrar') 
    169                 self.tv.heading(2, text='Default?') 
    170                 self.tv.column('#0', width=60) 
    171                 self.tv.column(0, width=300) 
    172                 self.tv.column(1, width=200) 
    173                 self.tv.column(2, width=60) 
    174                 self.tv.grid(column=0, row=0, rowspan=4, padx=5, pady=5) 
    175                  
    176                 ttk.Button(self, text='Add..', command=self._onBtnAdd).grid(column=1, row=0, padx=5) 
    177                 ttk.Button(self, text='Settings..', command=self._onBtnSettings).grid(column=1, row=1) 
    178                 ttk.Button(self, text='Set Default', command=self._onBtnSetDefault).grid(column=1, row=2) 
    179                 ttk.Button(self, text='Delete..', command=self._onBtnDelete).grid(column=1, row=3) 
    180  
    181         def _showAcc(self, acc): 
    182                 is_default = 'Yes' if acc.isValid() and acc.isDefault() else '' 
    183                 values = (acc.cfg.idUri, acc.cfg.regConfig.registrarUri, is_default) 
    184                 self.tv.insert('', 0, str(acc.randId), open=True, text=str(acc.cfg.priority), values=values) 
    185          
    186         def updateAccount(self, acc): 
    187                 is_default = 'Yes' if acc.isValid() and acc.isDefault() else '' 
    188                 values = (acc.cfg.idUri, acc.cfg.regConfig.registrarUri, is_default) 
    189                 self.tv.item(str(acc.randId), text=str(acc.cfg.priority), values=values) 
    190          
    191         def _getSelectedAcc(self): 
    192                 items = self.tv.selection() 
    193                 if not items: 
    194                         return None 
    195                 iid = int(items[0]) 
    196                 return [acc for acc in self.accList if acc.randId==iid][0] 
    197          
    198         def _onBtnAdd(self): 
    199                 cfg = pj.AccountConfig() 
    200                 dlg = accountsetting.Dialog(self.master, cfg) 
    201                 if dlg.doModal(): 
    202                         acc = Account(self.app) 
    203                         acc.cfg = cfg 
    204                         self._showAcc(acc) 
    205                         self.accList.append(acc) 
    206                         self.cfgChanged = True 
    207          
    208         def _onBtnSettings(self): 
    209                 acc = self._getSelectedAcc() 
    210                 if not acc: 
    211                         return 
    212                 dlg = accountsetting.Dialog(self.master, acc.cfg) 
    213                 if dlg.doModal(): 
    214                         self.updateAccount(acc) 
    215                         self.cfgChanged = True 
    216  
    217         def _onBtnDelete(self): 
    218                 acc = self._getSelectedAcc() 
    219                 if not acc: 
    220                         return 
    221                 msg = "Do you really want to delete account '%s'" % acc.cfg.idUri 
    222                 if msgbox.askquestion('Delete account?', msg, default=msgbox.NO) != u'yes': 
    223                         return 
    224                 self.accList.remove(acc) 
    225                 self.accDeletedList.append(acc) 
    226                 self.tv.delete( (str(acc.randId),) ) 
    227  
    228         def _onBtnSetDefault(self): 
    229                 acc = self._getSelectedAcc() 
    230                 if not acc: 
    231                         return 
    232                 if acc.isValid(): 
    233                         acc.setDefault() 
    234                 for acc in self.accList: 
    235                         self.updateAccount(acc) 
    236                  
    237                  
     152    """ 
     153    This implements a Frame which contains account list and buttons to operate 
     154    on them (Add, Modify, Delete, etc.). 
     155    """ 
     156    def __init__(self, parent, app, acc_list = []): 
     157        ttk.Frame.__init__(self, parent, name='acclist') 
     158        self.app = app 
     159        self.accList = acc_list 
     160        self.accDeletedList = [] 
     161        self.pack(expand='yes', fill='both') 
     162        self._createWidgets() 
     163        for acc in self.accList: 
     164            self._showAcc(acc) 
     165 
     166    def _createWidgets(self): 
     167        self.tv = ttk.Treeview(self, columns=('ID', 'Registrar', 'Default'), selectmode='browse') 
     168        self.tv.heading('#0', text='Priority') 
     169        self.tv.heading(0, text='ID') 
     170        self.tv.heading(1, text='Registrar') 
     171        self.tv.heading(2, text='Default?') 
     172        self.tv.column('#0', width=60) 
     173        self.tv.column(0, width=300) 
     174        self.tv.column(1, width=200) 
     175        self.tv.column(2, width=60) 
     176        self.tv.grid(column=0, row=0, rowspan=4, padx=5, pady=5) 
     177 
     178        ttk.Button(self, text='Add..', command=self._onBtnAdd).grid(column=1, row=0, padx=5) 
     179        ttk.Button(self, text='Settings..', command=self._onBtnSettings).grid(column=1, row=1) 
     180        ttk.Button(self, text='Set Default', command=self._onBtnSetDefault).grid(column=1, row=2) 
     181        ttk.Button(self, text='Delete..', command=self._onBtnDelete).grid(column=1, row=3) 
     182 
     183    def _showAcc(self, acc): 
     184        is_default = 'Yes' if acc.isValid() and acc.isDefault() else '' 
     185        values = (acc.cfg.idUri, acc.cfg.regConfig.registrarUri, is_default) 
     186        self.tv.insert('', 0, str(acc.randId), open=True, text=str(acc.cfg.priority), values=values) 
     187 
     188    def updateAccount(self, acc): 
     189        is_default = 'Yes' if acc.isValid() and acc.isDefault() else '' 
     190        values = (acc.cfg.idUri, acc.cfg.regConfig.registrarUri, is_default) 
     191        self.tv.item(str(acc.randId), text=str(acc.cfg.priority), values=values) 
     192 
     193    def _getSelectedAcc(self): 
     194        items = self.tv.selection() 
     195        if not items: 
     196            return None 
     197        iid = int(items[0]) 
     198        return [acc for acc in self.accList if acc.randId==iid][0] 
     199 
     200    def _onBtnAdd(self): 
     201        cfg = pj.AccountConfig() 
     202        dlg = accountsetting.Dialog(self.master, cfg) 
     203        if dlg.doModal(): 
     204            acc = Account(self.app) 
     205            acc.cfg = cfg 
     206            self._showAcc(acc) 
     207            self.accList.append(acc) 
     208            self.cfgChanged = True 
     209 
     210    def _onBtnSettings(self): 
     211        acc = self._getSelectedAcc() 
     212        if not acc: 
     213            return 
     214        dlg = accountsetting.Dialog(self.master, acc.cfg) 
     215        if dlg.doModal(): 
     216            self.updateAccount(acc) 
     217            self.cfgChanged = True 
     218 
     219    def _onBtnDelete(self): 
     220        acc = self._getSelectedAcc() 
     221        if not acc: 
     222            return 
     223        msg = "Do you really want to delete account '%s'" % acc.cfg.idUri 
     224        if msgbox.askquestion('Delete account?', msg, default=msgbox.NO) != u'yes': 
     225            return 
     226        self.accList.remove(acc) 
     227        self.accDeletedList.append(acc) 
     228        self.tv.delete( (str(acc.randId),) ) 
     229 
     230    def _onBtnSetDefault(self): 
     231        acc = self._getSelectedAcc() 
     232        if not acc: 
     233            return 
     234        if acc.isValid(): 
     235            acc.setDefault() 
     236        for acc in self.accList: 
     237            self.updateAccount(acc) 
     238 
     239 
    238240if __name__ == '__main__': 
    239         application.main() 
     241    application.main() 
Note: See TracChangeset for help on using the changeset viewer.