summaryrefslogtreecommitdiff
path: root/pjsip-apps/src/pygui/settings.py
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2014-01-16 05:30:46 +0000
committerLiong Sauw Ming <ming@teluu.com>2014-01-16 05:30:46 +0000
commite56ea14ab8531ee3cec375460577d1b89bf62e26 (patch)
treedf77c3acb961514b2022ee9e030071b691145920 /pjsip-apps/src/pygui/settings.py
parentbd1c47e995a3a844868f1d4dcc8f77f163ae721b (diff)
Closed #1723: Merging pjsua2 branch into trunk
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4704 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip-apps/src/pygui/settings.py')
-rw-r--r--pjsip-apps/src/pygui/settings.py362
1 files changed, 362 insertions, 0 deletions
diff --git a/pjsip-apps/src/pygui/settings.py b/pjsip-apps/src/pygui/settings.py
new file mode 100644
index 00000000..25f053e2
--- /dev/null
+++ b/pjsip-apps/src/pygui/settings.py
@@ -0,0 +1,362 @@
+# $Id$
+#
+# pjsua Python GUI Demo
+#
+# Copyright (C)2013 Teluu Inc. (http://www.teluu.com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+import sys
+if sys.version_info[0] >= 3: # Python 3
+ import tkinter as tk
+ from tkinter import ttk
+ from tkinter import messagebox as msgbox
+else:
+ import Tkinter as tk
+ import tkMessageBox as msgbox
+ import ttk
+
+import pjsua2 as pj
+#import application
+
+# Transport setting
+class SipTransportConfig:
+ def __init__(self, type, enabled):
+ #pj.PersistentObject.__init__(self)
+ self.type = type
+ self.enabled = enabled
+ self.config = pj.TransportConfig()
+ def readObject(self, node):
+ child_node = node.readContainer("SipTransport")
+ self.type = child_node.readInt("type")
+ self.enabled = child_node.readBool("enabled")
+ self.config.readObject(child_node)
+ def writeObject(self, node):
+ child_node = node.writeNewContainer("SipTransport")
+ child_node.writeInt("type", self.type)
+ child_node.writeBool("enabled", self.enabled)
+ self.config.writeObject(child_node)
+
+# Account setting with buddy list
+class AccConfig:
+ def __init__(self):
+ self.enabled = True
+ self.config = pj.AccountConfig()
+ self.buddyConfigs = []
+ def readObject(self, node):
+ acc_node = node.readContainer("Account")
+ self.enabled = acc_node.readBool("enabled")
+ self.config.readObject(acc_node)
+ buddy_node = acc_node.readArray("buddies")
+ while buddy_node.hasUnread():
+ buddy_cfg = pj.BuddyConfig()
+ buddy_cfg.readObject(buddy_node)
+ self.buddyConfigs.append(buddy_cfg)
+ def writeObject(self, node):
+ acc_node = node.writeNewContainer("Account")
+ acc_node.writeBool("enabled", self.enabled)
+ self.config.writeObject(acc_node)
+ buddy_node = acc_node.writeNewArray("buddies")
+ for buddy in self.buddyConfigs:
+ buddy_node.writeObject(buddy)
+
+
+# Master settings
+class AppConfig:
+ def __init__(self):
+ self.epConfig = pj.EpConfig() # pj.EpConfig()
+ self.udp = SipTransportConfig(pj.PJSIP_TRANSPORT_UDP, True)
+ self.tcp = SipTransportConfig(pj.PJSIP_TRANSPORT_TCP, True)
+ self.tls = SipTransportConfig(pj.PJSIP_TRANSPORT_TLS, False)
+ self.accounts = [] # Array of AccConfig
+
+ def loadFile(self, file):
+ json = pj.JsonDocument()
+ json.loadFile(file)
+ root = json.getRootContainer()
+ self.epConfig = pj.EpConfig()
+ self.epConfig.readObject(root)
+
+ tp_node = root.readArray("transports")
+ self.udp.readObject(tp_node)
+ self.tcp.readObject(tp_node)
+ if tp_node.hasUnread():
+ self.tls.readObject(tp_node)
+
+ acc_node = root.readArray("accounts")
+ while acc_node.hasUnread():
+ acfg = AccConfig()
+ acfg.readObject(acc_node)
+ self.accounts.append(acfg)
+
+ def saveFile(self,file):
+ json = pj.JsonDocument()
+
+ # Write endpoint config
+ json.writeObject(self.epConfig)
+
+ # Write transport config
+ tp_node = json.writeNewArray("transports")
+ self.udp.writeObject(tp_node)
+ self.tcp.writeObject(tp_node)
+ self.tls.writeObject(tp_node)
+
+ # Write account configs
+ node = json.writeNewArray("accounts")
+ for acc in self.accounts:
+ acc.writeObject(node)
+
+ json.saveFile(file)
+
+
+# Settings dialog
+class Dialog(tk.Toplevel):
+ """
+ This implements account settings dialog to manipulate account settings.
+ """
+ def __init__(self, parent, cfg):
+ tk.Toplevel.__init__(self, parent)
+ self.transient(parent)
+ self.parent = parent
+ self.title('Settings')
+
+ self.frm = ttk.Frame(self)
+ self.frm.pack(expand='yes', fill='both')
+
+ self.isOk = False
+ self.cfg = cfg
+
+ self.createWidgets()
+
+ def doModal(self):
+ if self.parent:
+ self.parent.wait_window(self)
+ else:
+ self.wait_window(self)
+ return self.isOk
+
+ def createWidgets(self):
+ # The notebook
+ self.frm.rowconfigure(0, weight=1)
+ self.frm.rowconfigure(1, weight=0)
+ self.frm.columnconfigure(0, weight=1)
+ self.frm.columnconfigure(1, weight=1)
+ self.wTab = ttk.Notebook(self.frm)
+ self.wTab.grid(column=0, row=0, columnspan=2, padx=10, pady=10, ipadx=20, ipady=20, sticky=tk.N+tk.S+tk.W+tk.E)
+
+ # Main buttons
+ btnOk = ttk.Button(self.frm, text='Ok', command=self.onOk)
+ btnOk.grid(column=0, row=1, sticky=tk.E, padx=20, pady=10)
+ btnCancel = ttk.Button(self.frm, text='Cancel', command=self.onCancel)
+ btnCancel.grid(column=1, row=1, sticky=tk.W, padx=20, pady=10)
+
+ # Tabs
+ self.createBasicTab()
+ self.createNetworkTab()
+ self.createMediaTab()
+
+ def createBasicTab(self):
+ # Prepare the variables to set/receive values from GUI
+ self.cfgLogFile = tk.StringVar(value=self.cfg.epConfig.logConfig.filename)
+ self.cfgLogAppend = tk.BooleanVar(value=True if (self.cfg.epConfig.logConfig.fileFlags & pj.PJ_O_APPEND) else False)
+
+ # Build the tab page
+ frm = ttk.Frame(self.frm)
+ frm.columnconfigure(0, weight=1)
+ frm.columnconfigure(1, weight=2)
+ row = 0
+ ttk.Label(frm, text='User Agent:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Label(frm, text=self.cfg.epConfig.uaConfig.userAgent).grid(row=row, column=1, sticky=tk.W, pady=2, padx=6)
+ row += 1
+ ttk.Label(frm, text='Max calls:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Label(frm, text=str(self.cfg.epConfig.uaConfig.maxCalls)).grid(row=row, column=1, sticky=tk.W, pady=2, padx=6)
+ row += 1
+ ttk.Label(frm, text='Log file:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Entry(frm, textvariable=self.cfgLogFile, width=32).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Checkbutton(frm, text='Append log file', variable=self.cfgLogAppend).grid(row=row, column=1, sticky=tk.W, padx=6, pady=2)
+
+ self.wTab.add(frm, text='Basic')
+
+ def createNetworkTab(self):
+ self.cfgNameserver = tk.StringVar()
+ if len(self.cfg.epConfig.uaConfig.nameserver):
+ self.cfgNameserver.set(self.cfg.epConfig.uaConfig.nameserver[0])
+ self.cfgStunServer = tk.StringVar()
+ if len(self.cfg.epConfig.uaConfig.stunServer):
+ self.cfgStunServer.set(self.cfg.epConfig.uaConfig.stunServer[0])
+ self.cfgStunIgnoreError = tk.BooleanVar(value=self.cfg.epConfig.uaConfig.stunIgnoreFailure)
+
+ self.cfgUdpEnabled = tk.BooleanVar(value=self.cfg.udp.enabled)
+ self.cfgUdpPort = tk.IntVar(value=self.cfg.udp.config.port)
+ self.cfgTcpEnabled = tk.BooleanVar(value=self.cfg.tcp.enabled)
+ self.cfgTcpPort = tk.IntVar(value=self.cfg.tcp.config.port)
+ self.cfgTlsEnabled = tk.BooleanVar(value=self.cfg.tls.enabled)
+ self.cfgTlsPort = tk.IntVar(value=self.cfg.tls.config.port)
+
+ self.cfgTlsCaFile = tk.StringVar(value=self.cfg.tls.config.tlsConfig.CaListFile)
+ self.cfgTlsCertFile = tk.StringVar(value=self.cfg.tls.config.tlsConfig.certFile)
+ self.cfgTlsVerifyClient = tk.BooleanVar(value=self.cfg.tls.config.tlsConfig.verifyClient)
+ self.cfgTlsVerifyServer = tk.BooleanVar(value=self.cfg.tls.config.tlsConfig.verifyServer)
+
+ # Build the tab page
+ frm = ttk.Frame(self.frm)
+ frm.columnconfigure(0, weight=1)
+ frm.columnconfigure(1, weight=2)
+ row = 0
+ #ttk.Label(frm, text='UDP transport:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Checkbutton(frm, text='Enable UDP transport', variable=self.cfgUdpEnabled).grid(row=row, column=0, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Label(frm, text='UDP port:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=0, to=65535, textvariable=self.cfgUdpPort, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ ttk.Label(frm, text='(0 for any)').grid(row=row, column=1, sticky=tk.E, pady=6, padx=6)
+ row += 1
+ #ttk.Label(frm, text='TCP transport:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Checkbutton(frm, text='Enable TCP transport', variable=self.cfgTcpEnabled).grid(row=row, column=0, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Label(frm, text='TCP port:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=0, to=65535, textvariable=self.cfgTcpPort, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ ttk.Label(frm, text='(0 for any)').grid(row=row, column=1, sticky=tk.E, pady=6, padx=6)
+ row += 1
+ #ttk.Label(frm, text='TLS transport:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Checkbutton(frm, text='Enable TLS transport', variable=self.cfgTlsEnabled).grid(row=row, column=0, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Label(frm, text='TLS port:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=0, to=65535, textvariable=self.cfgTlsPort, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ ttk.Label(frm, text='(0 for any)').grid(row=row, column=1, sticky=tk.E, pady=6, padx=6)
+ row += 1
+ ttk.Label(frm, text='TLS CA file:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Entry(frm, textvariable=self.cfgTlsCaFile, width=32).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='TLS cert file:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Entry(frm, textvariable=self.cfgTlsCertFile, width=32).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Checkbutton(frm, text='TLS verify server', variable=self.cfgTlsVerifyServer).grid(row=row, column=1, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Checkbutton(frm, text='TLS verify client', variable=self.cfgTlsVerifyClient).grid(row=row, column=1, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Label(frm, text='DNS and STUN:').grid(row=row, column=0, sticky=tk.W, pady=2, padx=8)
+ row += 1
+ ttk.Label(frm, text='Nameserver:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Entry(frm, textvariable=self.cfgNameserver, width=32).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='STUN Server:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Entry(frm, textvariable=self.cfgStunServer, width=32).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Checkbutton(frm, text='Ignore STUN failure at startup', variable=self.cfgStunIgnoreError).grid(row=row, column=1, sticky=tk.W, padx=6, pady=2)
+
+ self.wTab.add(frm, text='Network')
+
+ def createMediaTab(self):
+ self.cfgClockrate = tk.IntVar(value=self.cfg.epConfig.medConfig.clockRate)
+ self.cfgSndClockrate = tk.IntVar(value=self.cfg.epConfig.medConfig.sndClockRate)
+ self.cfgAudioPtime = tk.IntVar(value=self.cfg.epConfig.medConfig.audioFramePtime)
+ self.cfgMediaQuality = tk.IntVar(value=self.cfg.epConfig.medConfig.quality)
+ self.cfgCodecPtime = tk.IntVar(value=self.cfg.epConfig.medConfig.ptime)
+ self.cfgVad = tk.BooleanVar(value=not self.cfg.epConfig.medConfig.noVad)
+ self.cfgEcTailLen = tk.IntVar(value=self.cfg.epConfig.medConfig.ecTailLen)
+
+ # Build the tab page
+ frm = ttk.Frame(self.frm)
+ frm.columnconfigure(0, weight=1)
+ frm.columnconfigure(1, weight=2)
+ row = 0
+ ttk.Label(frm, text='Max media ports:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Label(frm, text=str(self.cfg.epConfig.medConfig.maxMediaPorts)).grid(row=row, column=1, sticky=tk.W, pady=2, padx=6)
+ row += 1
+ ttk.Label(frm, text='Core clock rate:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=8000, to=48000, increment=8000, textvariable=self.cfgClockrate, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='Snd device clock rate:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=0, to=48000, increment=8000, textvariable=self.cfgSndClockrate, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ ttk.Label(frm, text='(0: follow core)').grid(row=row, column=1, sticky=tk.E, pady=6, padx=6)
+ row += 1
+ ttk.Label(frm, text='Core ptime:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=10, to=400, increment=10, textvariable=self.cfgAudioPtime, width=3).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='RTP ptime:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=20, to=400, increment=10, textvariable=self.cfgCodecPtime, width=3).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='Media quality (1-10):').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=1, to=10, textvariable=self.cfgMediaQuality, width=5).grid(row=row, column=1, sticky=tk.W, padx=6)
+ row += 1
+ ttk.Label(frm, text='VAD:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ ttk.Checkbutton(frm, text='Enable', variable=self.cfgVad).grid(row=row, column=1, sticky=tk.W, padx=6, pady=2)
+ row += 1
+ ttk.Label(frm, text='Echo canceller tail length:').grid(row=row, column=0, sticky=tk.E, pady=2, padx=8)
+ tk.Spinbox(frm, from_=0, to=400, increment=10, textvariable=self.cfgEcTailLen, width=3).grid(row=row, column=1, sticky=tk.W, padx=6)
+ ttk.Label(frm, text='(ms, 0 to disable)').grid(row=row, column=1, sticky=tk.E, pady=6, padx=6)
+
+ self.wTab.add(frm, text='Media')
+
+ def onOk(self):
+ # Check basic settings
+ errors = "";
+ if errors:
+ msgbox.showerror("Error detected:", errors)
+ return
+
+ # Basic settings
+ self.cfg.epConfig.logConfig.filename = self.cfgLogFile.get()
+ flags = pj.PJ_O_APPEND if self.cfgLogAppend.get() else 0
+ self.cfg.epConfig.logConfig.fileFlags = self.cfg.epConfig.logConfig.fileFlags | flags
+
+ # Network settings
+ self.cfg.epConfig.uaConfig.nameserver.clear()
+ if len(self.cfgNameserver.get()):
+ self.cfg.epConfig.uaConfig.nameserver.append(self.cfgNameserver.get())
+ self.cfg.epConfig.uaConfig.stunServer.clear()
+ if len(self.cfgStunServer.get()):
+ self.cfg.epConfig.uaConfig.stunServer.append(self.cfgStunServer.get())
+
+ self.cfg.epConfig.uaConfig.stunIgnoreFailure = self.cfgStunIgnoreError.get()
+
+ self.cfg.udp.enabled = self.cfgUdpEnabled.get()
+ self.cfg.udp.config.port = self.cfgUdpPort.get()
+ self.cfg.tcp.enabled = self.cfgTcpEnabled.get()
+ self.cfg.tcp.config.port = self.cfgTcpPort.get()
+ self.cfg.tls.enabled = self.cfgTlsEnabled.get()
+ self.cfg.tls.config.port = self.cfgTlsPort.get()
+
+ self.cfg.tls.config.tlsConfig.CaListFile = self.cfgTlsCaFile.get()
+ self.cfg.tls.config.tlsConfig.certFile = self.cfgTlsCertFile.get()
+ self.cfg.tls.config.tlsConfig.verifyClient = self.cfgTlsVerifyClient.get()
+ self.cfg.tls.config.tlsConfig.verifyServer = self.cfgTlsVerifyServer.get()
+
+ # Media
+ self.cfg.epConfig.medConfig.clockRate = self.cfgClockrate.get()
+ self.cfg.epConfig.medConfig.sndClockRate = self.cfgSndClockrate.get()
+ self.cfg.epConfig.medConfig.audioFramePtime = self.cfgAudioPtime.get()
+ self.cfg.epConfig.medConfig.quality = self.cfgMediaQuality.get()
+ self.cfg.epConfig.medConfig.ptime = self.cfgCodecPtime.get()
+ self.cfg.epConfig.medConfig.noVad = not self.cfgVad.get()
+ self.cfg.epConfig.medConfig.ecTailLen = self.cfgEcTailLen.get()
+
+ self.isOk = True
+ self.destroy()
+
+ def onCancel(self):
+ self.destroy()
+
+
+if __name__ == '__main__':
+ #application.main()
+ acfg = AppConfig()
+ acfg.loadFile('pygui.js')
+
+ dlg = Dialog(None, acfg)
+ if dlg.doModal():
+ acfg.saveFile('pygui.js')
+ \ No newline at end of file