4 * An OPAL GUI phone application.
6 * Open Phone Abstraction Library (OPAL)
7 * Formally known as the Open H323 project.
9 * Copyright (c) 2004 Post Increment
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.0 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18 * the License for the specific language governing rights and limitations
21 * The Original Code is Open Phone client.
23 * The Initial Developer of the Original Code is Post Increment
28 * Revision 1.19 2007/06/06 09:08:56 rjongbloed
29 * Fixed deadlocks in OpenPhone Timer/GUI interaction.
31 * Revision 1.18 2007/05/20 08:16:12 rjongbloed
32 * Added various handlers to manage subscriptions for presence, message
33 * waiting indications, registrations, state publishing,
34 * message conversations, ...
36 * Revision 1.17 2007/05/10 01:03:54 rjongbloed
37 * Updated build for wxWidgets 2.8.x
39 * Revision 1.16 2007/04/03 07:59:13 rjongbloed
40 * Warning: API change to PCSS callbacks:
41 * changed return on OnShowIncoming to BOOL, now agrees with
42 * documentation and allows UI to abort calls early.
43 * added BOOL to AcceptIncomingConnection indicating the
44 * supplied token is invalid.
45 * removed redundent OnGetDestination() function, was never required.
47 * Revision 1.15 2006/11/19 06:06:01 rjongbloed
48 * Added override for dialing on a LID to use unique speed dial code immediately.
50 * Revision 1.14 2006/11/12 03:39:17 rjongbloed
51 * Fixed setting and saving of LID country code from Options dialog.
53 * Revision 1.13 2006/10/02 13:30:51 rjongbloed
56 * Revision 1.12 2006/09/16 04:20:36 rjongbloed
57 * Fixed crash when entering opetions dialog.
58 * Added recent calls list to Call dialog.
59 * Added "no trace" version.
61 * Revision 1.11 2006/09/07 10:09:24 rjongbloed
62 * Linux/GNU compiler compatibility
64 * Revision 1.10 2006/08/29 08:54:36 rjongbloed
67 * Revision 1.9 2006/08/17 23:09:03 rjongbloed
68 * Added volume controls
70 * Revision 1.8 2006/08/15 12:10:01 rjongbloed
71 * Added local interfaces to config dialog
73 * Revision 1.7 2006/08/14 22:39:27 rjongbloed
74 * Added aslias to config dialog
76 * Revision 1.6 2006/08/13 08:33:36 rjongbloed
77 * Completed bandwidth configuration from options dialog.
79 * Revision 1.5 2006/08/13 04:41:39 rjongbloed
80 * Fixed saving of ring device name
82 * Revision 1.4 2006/07/31 10:57:52 rjongbloed
83 * Added play of WAV file on incoming calls.
85 * Revision 1.3 2006/07/31 08:05:24 rjongbloed
86 * Fixed unix version of icons.
87 * Fixed some GNU compiler compatibility issues.
89 * Revision 1.2 2006/07/21 23:41:28 dereksmithies
90 * Move main.cpp contents to main.cxx. This fixes many issues under linux.
92 * Revision 1.37 2006/07/19 10:41:51 dereksmithies
93 * First steps towards having a unix compiled openphone.
95 * Revision 1.36 2006/04/30 10:36:24 rjongbloed
96 * Added icons to speed dial list.
98 * Revision 1.35 2006/04/09 12:15:30 rjongbloed
99 * Added extra trace log to dump all known media formats and their options.
101 * Revision 1.34 2005/12/11 19:14:21 dsandras
102 * Added support for setting a different user name and authentication user name
103 * as required by some providers like digisip.
105 * Revision 1.33 2005/08/31 13:21:20 rjongbloed
106 * Moved some video options to be in the options list from OpalMediaFormat
107 * Added selection of video grabber preview window.
109 * Revision 1.32 2005/08/24 10:43:51 rjongbloed
110 * Changed create video functions yet again so can return pointers that are not to be deleted.
112 * Revision 1.31 2005/08/24 10:21:36 rjongbloed
113 * Added function to create video output windows, can now get correct titles.
115 * Revision 1.30 2005/08/10 08:07:44 rjongbloed
116 * Upgraded to support wxWidgets 2.6
117 * Also improved build so uses WXDIR environment variable
119 * Revision 1.29 2005/07/09 07:05:16 rjongbloed
120 * Changed so resources are included in compile and not separate file at run time.
121 * General code clean ups.
123 * Revision 1.28 2005/06/02 13:21:49 rjongbloed
124 * Save and restore media format options to registry.
125 * Added check for valid value for media format option in dialog.
127 * Revision 1.27 2005/02/21 12:19:49 rjongbloed
128 * Added new "options list" to the OpalMediaFormat class.
130 * Revision 1.26 2004/10/06 13:08:19 rjongbloed
131 * Implemented partial support for LIDs
133 * Revision 1.25 2004/10/03 14:16:34 rjongbloed
134 * Added panels for calling, answering and in call phases.
136 * Revision 1.24 2004/09/29 12:47:39 rjongbloed
137 * Added gatekeeper support
139 * Revision 1.23 2004/09/29 12:02:40 rjongbloed
140 * Added popup menu to edit Speed DIals
142 * Revision 1.22 2004/09/28 23:00:17 rjongbloed
143 * Added ability to add and edit Speed DIals
145 * Revision 1.21 2004/08/22 12:27:45 rjongbloed
146 * More work on SIP registration, time to live refresh and deregistration on exit.
148 * Revision 1.20 2004/08/14 07:56:30 rjongbloed
149 * Major revision to utilise the PSafeCollection classes for the connections and calls.
151 * Revision 1.19 2004/07/17 08:21:24 rjongbloed
152 * Added ability to manipulate codec lists
154 * Revision 1.18 2004/07/14 13:17:42 rjongbloed
155 * Added saving of the width of columns in the speed dial list.
156 * Fixed router display in options dialog so is empty if IP address invalid.
158 * Revision 1.17 2004/07/11 12:42:11 rjongbloed
159 * Added function on endpoints to get the list of all media formats any
160 * connection the endpoint may create can support.
162 * Revision 1.16 2004/07/04 12:53:09 rjongbloed
163 * Added support for route editing.
165 * Revision 1.15 2004/06/05 14:37:03 rjongbloed
166 * More implemntation of options dialog.
168 * Revision 1.14 2004/05/25 12:55:52 rjongbloed
169 * Added all silence suppression modes to Options dialog.
171 * Revision 1.13 2004/05/24 13:44:03 rjongbloed
172 * More implementation on OPAL OpenPhone.
174 * Revision 1.12 2004/05/15 12:18:23 rjongbloed
175 * More work on wxWindows based OpenPhone
177 * Revision 1.11 2004/05/12 12:41:38 rjongbloed
178 * More work on wxWindows based OpenPhone
180 * Revision 1.10 2004/05/09 13:24:25 rjongbloed
181 * More work on wxWindows based OpenPhone
183 * Revision 1.9 2004/05/06 13:23:43 rjongbloed
184 * Work on wxWindows based OpenPhone
186 * Revision 1.8 2004/05/01 13:38:05 rjongbloed
187 * Some early implementation of wxWIndows based OPAL GUI client.
192 #pragma implementation
199 #include <wx/config.h>
200 #include <wx/filesys.h>
201 #include <wx/gdicmn.h> //Required for icons on linux.
202 #include <wx/image.h>
203 #include <wx/listctrl.h>
204 #include <wx/splitter.h>
205 #include <wx/valgen.h>
206 #include <wx/notebook.h>
207 #undef LoadMenu // Bizarre but necessary before the xml code
208 #include <wx/xrc/xmlres.h>
210 #include <opal/transcoders.h>
211 #include <opal/ivr.h>
212 #include <lids/lidep.h>
213 #include <ptclib/pstun.h>
216 #if defined(__WXGTK__) || \
217 defined(__WXMOTIF__) || \
218 defined(__WXX11__) || \
219 defined(__WXMAC__) || \
220 defined(__WXMGL__) || \
222 #include "openphone.xpm"
223 #include "h323phone.xpm"
224 #include "sipphone.xpm"
225 #include "otherphone.xpm"
226 #include "smallphone.xpm"
230 extern void InitXmlResource(); // From resource.cpp whichis compiled openphone.xrc
232 // Definitions of the configuration file section and key names
234 #define DEF_FIELD(name) static const char name##Key[] = #name
236 static const char AppearanceGroup
[] = "/Appearance";
237 DEF_FIELD(MainFrameX
);
238 DEF_FIELD(MainFrameY
);
239 DEF_FIELD(MainFrameWidth
);
240 DEF_FIELD(MainFrameHeight
);
241 DEF_FIELD(SashPosition
);
242 DEF_FIELD(ActiveView
);
244 static const char GeneralGroup
[] = "/General";
246 DEF_FIELD(DisplayName
);
247 DEF_FIELD(RingSoundDeviceName
);
248 DEF_FIELD(RingSoundFileName
);
249 DEF_FIELD(AutoAnswer
);
250 DEF_FIELD(IVRScript
);
251 DEF_FIELD(SpeakerVolume
);
252 DEF_FIELD(MicrophoneVolume
);
254 static const char NetworkingGroup
[] = "/Networking";
255 DEF_FIELD(Bandwidth
);
256 DEF_FIELD(TCPPortBase
);
257 DEF_FIELD(TCPPortMax
);
258 DEF_FIELD(UDPPortBase
);
259 DEF_FIELD(UDPPortMax
);
260 DEF_FIELD(RTPPortBase
);
261 DEF_FIELD(RTPPortMax
);
263 DEF_FIELD(STUNServer
);
264 DEF_FIELD(NATRouter
);
266 static const char LocalInterfacesGroup
[] = "/Networking/Interfaces";
268 static const char AudioGroup
[] = "/Audio";
269 DEF_FIELD(SoundPlayer
);
270 DEF_FIELD(SoundRecorder
);
271 DEF_FIELD(SoundBuffers
);
272 DEF_FIELD(LineInterfaceDevice
);
275 DEF_FIELD(MinJitter
);
276 DEF_FIELD(MaxJitter
);
277 DEF_FIELD(SilenceSuppression
);
278 DEF_FIELD(SilenceThreshold
);
279 DEF_FIELD(SignalDeadband
);
280 DEF_FIELD(SilenceDeadband
);
282 static const char VideoGroup
[] = "/Video";
283 DEF_FIELD(VideoGrabber
);
284 DEF_FIELD(VideoGrabFormat
);
285 DEF_FIELD(VideoGrabSource
);
286 DEF_FIELD(VideoGrabFrameRate
);
287 DEF_FIELD(VideoGrabPreview
);
288 DEF_FIELD(VideoFlipLocal
);
289 DEF_FIELD(VideoAutoTransmit
);
290 DEF_FIELD(VideoAutoReceive
);
291 DEF_FIELD(VideoFlipRemote
);
293 static const char CodecsGroup
[] = "/Codecs";
294 static const char CodecNameKey
[] = "Name";
296 static const char H323Group
[] = "/H.323";
297 DEF_FIELD(GatekeeperMode
);
298 DEF_FIELD(GatekeeperAddress
);
299 DEF_FIELD(GatekeeperIdentifier
);
300 DEF_FIELD(GatekeeperTTL
);
301 DEF_FIELD(GatekeeperLogin
);
302 DEF_FIELD(GatekeeperPassword
);
303 DEF_FIELD(DTMFSendMode
);
304 DEF_FIELD(CallIntrusionProtectionLevel
);
305 DEF_FIELD(DisableFastStart
);
306 DEF_FIELD(DisableH245Tunneling
);
307 DEF_FIELD(DisableH245inSETUP
);
309 static const char H323AliasesGroup
[] = "/H.323/Aliases";
311 static const char SIPGroup
[] = "/SIP";
312 DEF_FIELD(SIPProxyUsed
);
314 DEF_FIELD(SIPProxyUsername
);
315 DEF_FIELD(SIPProxyPassword
);
316 DEF_FIELD(RegistrarUsed
);
317 DEF_FIELD(RegistrarName
);
318 DEF_FIELD(RegistrarUsername
);
319 DEF_FIELD(RegistrarPassword
);
320 DEF_FIELD(RegistrarTimeToLive
);
322 static const char RoutingGroup
[] = "/Routes";
325 static const char TracingGroup
[] = "/Tracing";
326 DEF_FIELD(EnableTracing
);
327 DEF_FIELD(TraceLevelThreshold
);
328 DEF_FIELD(TraceLevelNumber
);
329 DEF_FIELD(TraceFileLine
);
330 DEF_FIELD(TraceBlocks
);
331 DEF_FIELD(TraceDateTime
);
332 DEF_FIELD(TraceTimestamp
);
333 DEF_FIELD(TraceThreadName
);
334 DEF_FIELD(TraceThreadAddress
);
335 DEF_FIELD(TraceFileName
);
336 DEF_FIELD(TraceOptions
);
339 static const char SpeedDialsGroup
[] = "/Speed Dials";
340 static const char SpeedDialAddressKey
[] = "Address";
341 static const char SpeedDialNumberKey
[] = "Number";
342 static const char SpeedDialDescriptionKey
[] = "Description";
344 static const char RecentCallsGroup
[] = "/Recent Calls";
345 static const size_t MaxSavedRecentCalls
= 10;
348 ///////////////////////////////////////////////////////////////////////////////
350 template <class cls
> cls
* FindWindowByNameAs(wxWindow
* window
, const char * name
)
352 cls
* child
= dynamic_cast<cls
*>(window
->FindWindowByName(name
));
355 PAssertAlways("Cannot cast window object to class");
360 ///////////////////////////////////////////////////////////////////////////////
362 class TextCtrlChannel
: public PChannel
364 PCLASSINFO(TextCtrlChannel
, PChannel
)
366 TextCtrlChannel(wxTextCtrl
* textCtrl
= NULL
)
367 : m_textCtrl(textCtrl
)
371 const void * buf
, /// Pointer to a block of memory to write.
372 PINDEX len
/// Number of bytes to write.
374 if (m_textCtrl
== NULL
)
376 m_textCtrl
->WriteText(wxString((const wxChar
*)buf
, (size_t)len
));
381 wxTextCtrl
* textCtrl
382 ) { m_textCtrl
= textCtrl
; }
385 wxTextCtrl
* m_textCtrl
;
390 ///////////////////////////////////////////////////////////////////////////////
392 IMPLEMENT_APP(OpenPhoneApp
)
394 OpenPhoneApp::OpenPhoneApp()
395 : PProcess("Equivalence", "OpenPhone",
396 MAJOR_VERSION
, MINOR_VERSION
, BUILD_TYPE
, BUILD_NUMBER
)
398 wxConfig::Set(new wxConfig((const char *)GetName(), (const char *)GetManufacturer()));
402 void OpenPhoneApp::Main()
408 bool OpenPhoneApp::OnInit()
410 // Create the main frame window
411 MyManager
* main
= new MyManager();
414 bool ok
= main
->Initialise();
420 ///////////////////////////////////////////////////////////////////////////////
422 BEGIN_EVENT_TABLE(MyManager
, wxFrame
)
423 EVT_CLOSE(MyManager::OnClose
)
425 EVT_MENU_OPEN(MyManager::OnAdjustMenus
)
427 EVT_MENU(XRCID("MenuQuit"), MyManager::OnMenuQuit
)
428 EVT_MENU(XRCID("MenuAbout"), MyManager::OnMenuAbout
)
429 EVT_MENU(XRCID("MenuCall"), MyManager::OnMenuCall
)
430 EVT_MENU(XRCID("MenuAnswer"), MyManager::OnMenuAnswer
)
431 EVT_MENU(XRCID("MenuHangUp"), MyManager::OnMenuHangUp
)
432 EVT_MENU(XRCID("NewSpeedDial"), MyManager::OnNewSpeedDial
)
433 EVT_MENU(XRCID("ViewLarge"), MyManager::OnViewLarge
)
434 EVT_MENU(XRCID("ViewSmall"), MyManager::OnViewSmall
)
435 EVT_MENU(XRCID("ViewList"), MyManager::OnViewList
)
436 EVT_MENU(XRCID("ViewDetails"), MyManager::OnViewDetails
)
437 EVT_MENU(XRCID("EditSpeedDial"),MyManager::OnEditSpeedDial
)
438 EVT_MENU(XRCID("MenuOptions"), MyManager::OnOptions
)
440 EVT_SPLITTER_SASH_POS_CHANGED(SplitterID
, MyManager::OnSashPositioned
)
441 EVT_LIST_ITEM_ACTIVATED(SpeedDialsID
, MyManager::OnSpeedDialActivated
)
442 EVT_LIST_COL_END_DRAG(SpeedDialsID
, MyManager::OnSpeedDialColumnResize
)
443 EVT_LIST_ITEM_RIGHT_CLICK(SpeedDialsID
, MyManager::OnRightClick
)
446 MyManager::MyManager()
447 : wxFrame(NULL
, -1, wxT("OpenPhone"), wxDefaultPosition
, wxSize(640, 480)),
460 m_callState(IdleState
)
464 SetIcon(wxICON(AppIcon
));
466 // Make an image list containing large icons
467 m_imageListNormal
= new wxImageList(32, 32, true);
468 // Order here is important!!
469 m_imageListNormal
->Add(wxICON(OtherPhone
));
470 m_imageListNormal
->Add(wxICON(H323Phone
));
471 m_imageListNormal
->Add(wxICON(SIPPhone
));
473 m_imageListSmall
= new wxImageList(16, 16, true);
474 m_imageListSmall
->Add(wxICON(SmallPhone
));
476 m_RingSoundTimer
.SetNotifier(PCREATE_NOTIFIER(OnRingSoundAgain
));
480 MyManager::~MyManager()
482 LogWindow
.SetTextCtrl(NULL
);
486 // Must do this before we destroy the manager or a crash will result
488 potsEP
->RemoveAllLines();
490 delete m_imageListNormal
;
491 delete m_imageListSmall
;
495 bool MyManager::Initialise()
497 wxImage::AddHandler(new wxGIFHandler
);
498 wxXmlResource::Get()->InitAllHandlers();
502 wxMenuBar
* menubar
= wxXmlResource::Get()->LoadMenuBar("MenuBar");
508 wxConfigBase
* config
= wxConfig::Get();
509 config
->SetPath(AppearanceGroup
);
512 if (config
->Read(MainFrameXKey
, &x
) && config
->Read(MainFrameYKey
, &y
))
516 if (config
->Read(MainFrameWidthKey
, &w
) && config
->Read(MainFrameHeightKey
, &h
))
519 // Make the content of the main window, speed dial and log panes inside a splitter
520 m_splitter
= new wxSplitterWindow(this, SplitterID
, wxDefaultPosition
, wxDefaultSize
, wxSP_3D
);
522 // Log window - gets informative text
523 m_logWindow
= new wxTextCtrl(m_splitter
, -1, wxEmptyString
,
524 wxDefaultPosition
, wxDefaultSize
,
525 wxTE_MULTILINE
| wxSUNKEN_BORDER
);
526 LogWindow
.SetTextCtrl(m_logWindow
);
527 m_logWindow
->SetForegroundColour(wxColour(0,255,0)); // Green
528 m_logWindow
->SetBackgroundColour(wxColour(0,0,0)); // Black
530 // Speed dial window - icons for each speed dial
532 if (!config
->Read(ActiveViewKey
, &i
) || i
< 0 || i
>= e_NumViews
)
536 static const char * const ViewMenuNames
[e_NumViews
] = {
537 "ViewLarge", "ViewSmall", "ViewList", "ViewDetails"
539 menubar
->Check(XRCID(ViewMenuNames
[i
]), true);
540 RecreateSpeedDials((SpeedDialViews
)i
);
542 // Speed dial panel switches to answer panel on ring
543 m_answerPanel
= new AnswerPanel(*this, m_splitter
);
544 m_answerPanel
->Show(false);
546 // Speed dial panel switches to calling panel on dial
547 m_callingPanel
= new CallingPanel(*this, m_splitter
);
548 m_callingPanel
->Show(false);
550 // Speed dial/Answer/Calling panel switches to "in call" panel on successful call establishment
551 m_inCallPanel
= new InCallPanel(*this, m_splitter
);
552 m_inCallPanel
->Show(false);
554 // Set up sizer to automatically resize the splitter to size of window
555 wxBoxSizer
* sizer
= new wxBoxSizer(wxVERTICAL
);
556 sizer
->Add(m_splitter
, 1, wxGROW
, 0);
559 // Show the frame window
563 ////////////////////////////////////////
565 config
->SetPath(TracingGroup
);
566 if (config
->Read(EnableTracingKey
, &m_enableTracing
, false) && m_enableTracing
&&
567 config
->Read(TraceFileNameKey
, &m_traceFileName
) && !m_traceFileName
.empty()) {
568 int traceLevelThreshold
= 3;
569 config
->Read(TraceLevelThresholdKey
, &traceLevelThreshold
);
570 int traceOptions
= PTrace::DateAndTime
|PTrace::Thread
|PTrace::FileAndLine
;
571 config
->Read(TraceOptionsKey
, &traceOptions
);
572 PTrace::Initialise(traceLevelThreshold
, m_traceFileName
, traceOptions
);
576 ////////////////////////////////////////
577 // Creating the endpoints
579 h323EP
= new MyH323EndPoint(*this);
583 sipEP
= new MySIPEndPoint(*this);
587 ivrEP
= new OpalIVREndPoint(*this);
590 potsEP
= new OpalPOTSEndPoint(*this);
591 pcssEP
= new MyPCSSEndPoint(*this);
595 int value1
= 0, value2
= 0;
597 ////////////////////////////////////////
599 config
->SetPath(GeneralGroup
);
600 if (config
->Read(UsernameKey
, &str
) && !str
.IsEmpty())
601 SetDefaultUserName(str
);
602 if (config
->Read(DisplayNameKey
, &str
) && !str
.IsEmpty())
603 SetDefaultDisplayName(str
);
605 if (!config
->Read(RingSoundDeviceNameKey
, &m_RingSoundDeviceName
))
606 m_RingSoundDeviceName
= PSoundChannel::GetDefaultDevice(PSoundChannel::Player
);
607 config
->Read(RingSoundFileNameKey
, &m_RingSoundFileName
);
609 config
->Read(AutoAnswerKey
, &m_autoAnswer
);
611 if (config
->Read(IVRScriptKey
, &str
))
612 ivrEP
->SetDefaultVXML(str
);
615 ////////////////////////////////////////
617 config
->SetPath(NetworkingGroup
);
618 if (config
->Read(BandwidthKey
, &value1
))
619 h323EP
->SetInitialBandwidth(value1
);
620 if (config
->Read(TCPPortBaseKey
, &value1
) && config
->Read(TCPPortMaxKey
, &value2
))
621 SetTCPPorts(value1
, value2
);
622 if (config
->Read(UDPPortBaseKey
, &value1
) && config
->Read(UDPPortMaxKey
, &value2
))
623 SetUDPPorts(value1
, value2
);
624 if (config
->Read(RTPPortBaseKey
, &value1
) && config
->Read(RTPPortMaxKey
, &value2
))
625 SetRtpIpPorts(value1
, value2
);
626 if (config
->Read(RTPTOSKey
, &value1
))
627 SetRtpIpTypeofService(value1
);
628 if (config
->Read(NATRouterKey
, &str
))
629 SetTranslationAddress(str
);
630 if (config
->Read(STUNServerKey
, &str
) && !str
.IsEmpty()) {
631 LogWindow
<< "STUN server \"" << str
<< "\" being contacted ..." << endl
;
632 LogWindow
<< "STUN server \"" << str
<< "\" replies " << SetSTUNServer(str
) << endl
;
635 config
->SetPath(LocalInterfacesGroup
);
638 if (config
->GetFirstEntry(entryName
, entryIndex
)) {
640 wxString localInterface
;
641 if (config
->Read(entryName
, &localInterface
) && !localInterface
.empty())
642 m_LocalInterfaces
.AppendString(localInterface
.c_str());
643 } while (config
->GetNextEntry(entryName
, entryIndex
));
648 ////////////////////////////////////////
650 config
->SetPath(AudioGroup
);
651 if (config
->Read(SoundPlayerKey
, &str
))
652 pcssEP
->SetSoundChannelPlayDevice(str
);
653 if (config
->Read(SoundRecorderKey
, &str
))
654 pcssEP
->SetSoundChannelRecordDevice(str
);
655 if (config
->Read(SoundBuffersKey
, &value1
))
656 pcssEP
->SetSoundChannelBufferDepth(value1
);
658 if (config
->Read(MinJitterKey
, &value1
)) {
659 config
->Read(MaxJitterKey
, &value2
, value1
);
660 SetAudioJitterDelay(value1
, value2
);
663 OpalSilenceDetector::Params silenceParams
= GetSilenceDetectParams();
664 if (config
->Read(SilenceSuppressionKey
, &value1
) && value1
>= 0 && value1
< OpalSilenceDetector::NumModes
)
665 silenceParams
.m_mode
= (OpalSilenceDetector::Mode
)value1
;
666 if (config
->Read(SilenceThresholdKey
, &value1
))
667 silenceParams
.m_threshold
= value1
;
668 if (config
->Read(SignalDeadbandKey
, &value1
))
669 silenceParams
.m_signalDeadband
= value1
*8;
670 if (config
->Read(SilenceDeadbandKey
, &value1
))
671 silenceParams
.m_silenceDeadband
= value1
*8;
672 SetSilenceDetectParams(silenceParams
);
674 if (config
->Read(LineInterfaceDeviceKey
, &str
) && potsEP
->AddDeviceName(str
)) {
675 OpalLine
* line
= potsEP
->GetLine("*");
676 if (PAssertNULL(line
) != NULL
) {
677 if (config
->Read(AECKey
, &value1
) && value1
>= 0 && value1
< OpalLineInterfaceDevice::AECError
)
678 line
->SetAEC((OpalLineInterfaceDevice::AECLevels
)value1
);
679 if (config
->Read(CountryKey
, &str
)) {
680 if (!line
->GetDevice().SetCountryCodeName(str
))
681 LogWindow
<< "Could not configure Line Interface Device to country \"" << str
<< '"' << endl
;
687 ////////////////////////////////////////
689 config
->SetPath(VideoGroup
);
690 PVideoDevice::OpenArgs videoArgs
= GetVideoInputDevice();
691 if (config
->Read(VideoGrabberKey
, &str
))
692 videoArgs
.deviceName
= (PString
)PString(str
.c_str());
693 if (config
->Read(VideoGrabFormatKey
, &value1
) && value1
>= 0 && value1
< PVideoDevice::NumVideoFormats
)
694 videoArgs
.videoFormat
= (PVideoDevice::VideoFormat
)value1
;
695 if (config
->Read(VideoGrabSourceKey
, &value1
))
696 videoArgs
.channelNumber
= value1
;
697 if (config
->Read(VideoGrabFrameRateKey
, &value1
))
698 videoArgs
.rate
= value1
;
699 config
->Read(VideoFlipLocalKey
, &videoArgs
.flip
);
700 SetVideoInputDevice(videoArgs
);
702 config
->Read(VideoGrabPreviewKey
, &m_VideoGrabPreview
);
703 if (config
->Read(VideoAutoTransmitKey
, &onoff
))
704 SetAutoStartTransmitVideo(onoff
);
705 if (config
->Read(VideoAutoReceiveKey
, &onoff
))
706 SetAutoStartReceiveVideo(onoff
);
708 videoArgs
= GetVideoOutputDevice();
709 config
->Read(VideoFlipRemoteKey
, &videoArgs
.flip
);
710 SetVideoOutputDevice(videoArgs
);
712 ////////////////////////////////////////
714 InitMediaInfo(pcssEP
->GetPrefixName(), pcssEP
->GetMediaFormats());
715 InitMediaInfo(potsEP
->GetPrefixName(), potsEP
->GetMediaFormats());
717 InitMediaInfo(ivrEP
->GetPrefixName(), ivrEP
->GetMediaFormats());
720 OpalMediaFormatList mediaFormats
;
721 mediaFormats
+= pcssEP
->GetMediaFormats();
722 mediaFormats
+= potsEP
->GetMediaFormats();
724 mediaFormats
+= ivrEP
->GetMediaFormats();
726 InitMediaInfo("sw", OpalTranscoder::GetPossibleFormats(mediaFormats
));
728 config
->SetPath(CodecsGroup
);
732 groupName
.sprintf("%04u", codecIndex
);
733 if (!config
->HasGroup(groupName
))
736 config
->SetPath(groupName
);
738 if (config
->Read(CodecNameKey
, &codecName
) && !codecName
.empty()) {
739 for (MyMediaList::iterator mm
= m_mediaInfo
.begin(); mm
!= m_mediaInfo
.end(); ++mm
) {
740 if (codecName
== mm
->mediaFormat
) {
741 mm
->preferenceOrder
= codecIndex
;
742 bool changedSomething
= false;
743 for (PINDEX i
= 0; i
< mm
->mediaFormat
.GetOptionCount(); i
++) {
744 const OpalMediaOption
& option
= mm
->mediaFormat
.GetOption(i
);
745 if (!option
.IsReadOnly()) {
746 PwxString codecOptionName
= option
.GetName();
747 PwxString codecOptionValue
;
748 PString oldOptionValue
;
749 mm
->mediaFormat
.GetOptionValue(codecOptionName
, oldOptionValue
);
750 if (config
->Read(codecOptionName
, &codecOptionValue
) &&
751 !codecOptionValue
.empty() && codecOptionValue
!= oldOptionValue
) {
752 if (mm
->mediaFormat
.SetOptionValue(codecOptionName
, codecOptionValue
))
753 changedSomething
= true;
757 if (changedSomething
)
758 OpalMediaFormat::SetRegisteredMediaFormat(mm
->mediaFormat
);
762 config
->SetPath("..");
769 PStringArray mediaFormatOrder
= GetMediaFormatOrder();
770 for (PINDEX i
= 0; i
< mediaFormatOrder
.GetSize(); i
++) {
771 for (MyMediaList::iterator mm
= m_mediaInfo
.begin(); mm
!= m_mediaInfo
.end(); ++mm
) {
772 if (mm
->mediaFormat
== mediaFormatOrder
[i
])
773 mm
->preferenceOrder
= codecIndex
++;
776 for (MyMediaList::iterator mm
= m_mediaInfo
.begin(); mm
!= m_mediaInfo
.end(); ++mm
) {
777 if (mm
->preferenceOrder
< 0)
778 mm
->preferenceOrder
= codecIndex
++;
784 mediaFormats
= OpalMediaFormat::GetAllRegisteredMediaFormats();
785 ostream
& traceStream
= PTrace::Begin(1, __FILE__
, __LINE__
);
786 traceStream
<< "OpenPhone\tRegistered media formats:\n";
787 for (PINDEX i
= 0; i
< mediaFormats
.GetSize(); i
++) {
788 traceStream
<< " " << mediaFormats
[i
] << '\n';
789 for (PINDEX j
= 0; j
< mediaFormats
[i
].GetOptionCount(); j
++) {
790 const OpalMediaOption
& option
= mediaFormats
[i
].GetOption(j
);
791 traceStream
<< " " << option
.GetName() << " = " << option
.AsString() << '\n';
794 traceStream
<< PTrace::End
;
797 ////////////////////////////////////////
799 config
->SetPath(H323AliasesGroup
);
800 if (config
->GetFirstEntry(entryName
, entryIndex
)) {
803 if (config
->Read(entryName
, &alias
) && !alias
.empty())
804 h323EP
->AddAliasName(alias
.c_str());
805 } while (config
->GetNextEntry(entryName
, entryIndex
));
808 config
->SetPath(H323Group
);
809 if (config
->Read(DTMFSendModeKey
, &value1
) && value1
>= 0 && value1
< H323Connection::NumSendUserInputModes
)
810 h323EP
->SetSendUserInputMode((H323Connection::SendUserInputModes
)value1
);
811 if (config
->Read(CallIntrusionProtectionLevelKey
, &value1
))
812 h323EP
->SetCallIntrusionProtectionLevel(value1
);
813 if (config
->Read(DisableFastStartKey
, &onoff
))
814 h323EP
->DisableFastStart(onoff
);
815 if (config
->Read(DisableH245TunnelingKey
, &onoff
))
816 h323EP
->DisableH245Tunneling(onoff
);
817 if (config
->Read(DisableH245inSETUPKey
, &onoff
))
818 h323EP
->DisableH245inSetup(onoff
);
820 PwxString username
, password
;
821 config
->Read(GatekeeperModeKey
, &m_gatekeeperMode
, 0);
822 if (m_gatekeeperMode
> 0) {
823 if (config
->Read(GatekeeperTTLKey
, &value1
))
824 h323EP
->SetGatekeeperTimeToLive(PTimeInterval(0, value1
));
826 config
->Read(GatekeeperLoginKey
, &username
, "");
827 config
->Read(GatekeeperPasswordKey
, &password
, "");
828 h323EP
->SetGatekeeperPassword(password
, username
);
830 config
->Read(GatekeeperAddressKey
, &m_gatekeeperAddress
, "");
831 config
->Read(GatekeeperIdentifierKey
, &m_gatekeeperIdentifier
, "");
832 if (!StartGatekeeper())
836 ////////////////////////////////////////
838 config
->SetPath(SIPGroup
);
839 const SIPURL
& proxy
= sipEP
->GetProxy();
841 config
->Read(SIPProxyUsedKey
, &m_SIPProxyUsed
, false);
842 config
->Read(SIPProxyKey
, &hostname
, PwxString(proxy
.GetHostName()));
843 config
->Read(SIPProxyUsernameKey
, &username
, PwxString(proxy
.GetUserName()));
844 config
->Read(SIPProxyPasswordKey
, &password
, PwxString(proxy
.GetPassword()));
846 sipEP
->SetProxy(hostname
, username
, password
);
848 if (config
->Read(RegistrarTimeToLiveKey
, &value1
))
849 sipEP
->SetRegistrarTimeToLive(PTimeInterval(0, value1
));
851 if (config
->Read(RegistrarUsedKey
, &m_registrarUsed
, false) &&
852 config
->Read(RegistrarNameKey
, &m_registrarName
) &&
853 config
->Read(RegistrarUsernameKey
, &m_registrarUser
) &&
854 config
->Read(RegistrarPasswordKey
, &m_registrarPassword
))
857 ////////////////////////////////////////
862 AddRouteEntry("pots:.*\\*.*\\*.* = sip:<dn2ip>");
863 AddRouteEntry("pots:.* = sip:<da>");
864 AddRouteEntry("pc:.* = sip:<da>");
872 if (h323EP
!= NULL
) {
873 AddRouteEntry("pots:.*\\*.*\\*.* = h323:<dn2ip>");
874 AddRouteEntry("pots:.* = h323:<da>");
875 AddRouteEntry("pc:.* = h323:<da>");
881 AddRouteEntry(".*:# = ivr:"); // A hash from anywhere goes to IVR
884 if (potsEP
!= NULL
&& potsEP
->GetLine("*") != NULL
) {
886 AddRouteEntry("h323:.* = pots:<da>");
889 AddRouteEntry("sip:.* = pots:<da>");
892 else if (pcssEP
!= NULL
) {
894 AddRouteEntry("h323:.* = pc:<da>");
897 AddRouteEntry("sip:.* = pc:<da>");
906 void MyManager::StartAllListeners()
909 h323EP
->RemoveListener(NULL
);
910 if (h323EP
->StartListeners(m_LocalInterfaces
))
911 LogWindow
<< "H.323 listening on " << setfill(',') << h323EP
->GetListeners() << setfill(' ') << endl
;
913 LogWindow
<< "H.323 listen failed";
914 if (!m_LocalInterfaces
.IsEmpty())
915 LogWindow
<< " with interfaces" << setfill(',') << m_LocalInterfaces
<< setfill(' ');
921 sipEP
->RemoveListener(NULL
);
922 if (sipEP
->StartListeners(m_LocalInterfaces
))
923 LogWindow
<< "SIP listening on " << setfill(',') << sipEP
->GetListeners() << setfill(' ') << endl
;
925 LogWindow
<< "SIP listen failed";
926 if (!m_LocalInterfaces
.IsEmpty())
927 LogWindow
<< " with interfaces" << setfill(',') << m_LocalInterfaces
<< setfill(' ');
934 void MyManager::RecreateSpeedDials(SpeedDialViews view
)
936 wxConfigBase
* config
= wxConfig::Get();
937 config
->SetPath(AppearanceGroup
);
939 config
->Write(ActiveViewKey
, view
);
941 wxListCtrl
* oldSpeedDials
= m_speedDials
;
943 static DWORD
const ListCtrlStyle
[e_NumViews
] = {
944 wxLC_ICON
, wxLC_SMALL_ICON
, wxLC_LIST
, wxLC_REPORT
947 m_speedDials
= new wxListCtrl(m_splitter
, SpeedDialsID
,
948 wxDefaultPosition
, wxDefaultSize
,
949 ListCtrlStyle
[view
] | wxLC_EDIT_LABELS
| wxSUNKEN_BORDER
);
951 if (view
!= e_ViewDetails
) {
952 m_speedDials
->SetImageList(m_imageListNormal
, wxIMAGE_LIST_NORMAL
);
953 m_speedDials
->SetImageList(m_imageListSmall
, wxIMAGE_LIST_SMALL
);
957 static const char * const titles
[e_NumColumns
] = { "Name", "Number", "Address", "Description" };
959 for (int i
= 0; i
< e_NumColumns
; i
++) {
960 m_speedDials
->InsertColumn(i
, titles
[i
]);
962 key
.sprintf("ColumnWidth%u", i
);
963 if (config
->Read(key
, &width
))
964 m_speedDials
->SetColumnWidth(i
, width
);
967 // Now either replace the top half of the splitter or set it for the first time
968 if (oldSpeedDials
== NULL
)
969 m_splitter
->SplitHorizontally(m_speedDials
, m_logWindow
);
971 m_splitter
->ReplaceWindow(oldSpeedDials
, m_speedDials
);
972 delete oldSpeedDials
;
975 if (config
->Read(SashPositionKey
, &width
))
976 m_splitter
->SetSashPosition(width
);
978 // Read the speed dials from the configuration
979 config
->SetPath(SpeedDialsGroup
);
982 if (config
->GetFirstGroup(groupName
, groupIndex
)) {
984 config
->SetPath(groupName
);
985 wxString number
, address
, description
;
986 if (config
->Read(SpeedDialAddressKey
, &address
) && !address
.empty()) {
988 if (view
== e_ViewLarge
) {
989 if (address
.StartsWith("h323"))
991 else if (address
.StartsWith("sip"))
995 int pos
= m_speedDials
->InsertItem(INT_MAX
, groupName
, icon
);
996 m_speedDials
->SetItem(pos
, e_NumberColumn
, config
->Read(SpeedDialNumberKey
, ""));
997 m_speedDials
->SetItem(pos
, e_AddressColumn
, address
);
998 m_speedDials
->SetItem(pos
, e_DescriptionColumn
, config
->Read(SpeedDialDescriptionKey
, ""));
1000 config
->SetPath("..");
1001 } while (config
->GetNextGroup(groupName
, groupIndex
));
1006 void MyManager::OnClose(wxCloseEvent
& /*event*/)
1008 ::wxBeginBusyCursor();
1010 wxConfigBase
* config
= wxConfig::Get();
1011 config
->SetPath(AppearanceGroup
);
1014 GetPosition(&x
, &y
);
1015 config
->Write(MainFrameXKey
, x
);
1016 config
->Write(MainFrameYKey
, y
);
1020 config
->Write(MainFrameWidthKey
, w
);
1021 config
->Write(MainFrameHeightKey
, h
);
1027 void MyManager::OnAdjustMenus(wxMenuEvent
& WXUNUSED(event
))
1029 wxMenuBar
* menubar
= GetMenuBar();
1030 menubar
->Enable(XRCID("MenuCall"), m_callState
== IdleState
);
1031 menubar
->Enable(XRCID("MenuAnswer"), m_callState
== RingingState
);
1032 menubar
->Enable(XRCID("MenuHangUp"), m_callState
== InCallState
);
1036 void MyManager::OnMenuQuit(wxCommandEvent
& WXUNUSED(event
))
1042 void MyManager::OnMenuAbout(wxCommandEvent
& WXUNUSED(event
))
1044 wxMessageDialog
dialog(this,
1045 _T("OpenPhone\nPost Increment (c) 2004"),
1046 _T("About OpenPhone"),
1052 void MyManager::OnMenuCall(wxCommandEvent
& WXUNUSED(event
))
1054 CallDialog
dlg(this);
1055 if (dlg
.ShowModal() == wxID_OK
)
1056 MakeCall(dlg
.m_Address
);
1060 void MyManager::OnMenuAnswer(wxCommandEvent
& WXUNUSED(event
))
1066 void MyManager::OnMenuHangUp(wxCommandEvent
& WXUNUSED(event
))
1072 void MyManager::OnNewSpeedDial(wxCommandEvent
& WXUNUSED(event
))
1074 wxString groupName
= "New Speed Dial";
1075 unsigned tieBreaker
= 0;
1076 int count
= m_speedDials
->GetItemCount();
1079 if (m_speedDials
->GetItemText(i
) != groupName
)
1082 groupName
.sprintf("New Speed Dial (%u)", ++tieBreaker
);
1087 int pos
= m_speedDials
->InsertItem(INT_MAX
, groupName
);
1088 m_speedDials
->SetItem(pos
, e_NumberColumn
, "");
1089 m_speedDials
->SetItem(pos
, e_AddressColumn
, "");
1090 m_speedDials
->SetItem(pos
, e_DescriptionColumn
, "");
1091 m_speedDials
->EditLabel(pos
);
1095 void MyManager::OnViewLarge(wxCommandEvent
& event
)
1097 GetMenuBar()->Check(event
.GetId(), true);
1098 RecreateSpeedDials(e_ViewLarge
);
1102 void MyManager::OnViewSmall(wxCommandEvent
& event
)
1104 GetMenuBar()->Check(event
.GetId(), true);
1105 RecreateSpeedDials(e_ViewSmall
);
1109 void MyManager::OnViewList(wxCommandEvent
& event
)
1111 GetMenuBar()->Check(event
.GetId(), true);
1112 RecreateSpeedDials(e_ViewList
);
1116 void MyManager::OnViewDetails(wxCommandEvent
& event
)
1118 GetMenuBar()->Check(event
.GetId(), true);
1119 RecreateSpeedDials(e_ViewDetails
);
1123 void MyManager::OnEditSpeedDial(wxCommandEvent
& WXUNUSED(event
))
1125 if (m_speedDials
->GetSelectedItemCount() == 1)
1126 EditSpeedDial(m_speedDials
->GetNextItem(-1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
));
1130 void MyManager::OnSashPositioned(wxSplitterEvent
& event
)
1132 wxConfigBase
* config
= wxConfig::Get();
1133 config
->SetPath(AppearanceGroup
);
1134 config
->Write(SashPositionKey
, event
.GetSashPosition());
1138 void MyManager::OnSpeedDialActivated(wxListEvent
& event
)
1141 item
.m_itemId
= event
.GetIndex();
1142 if (item
.m_itemId
< 0)
1145 item
.m_col
= e_AddressColumn
;
1146 item
.m_mask
= wxLIST_MASK_TEXT
;
1147 if (m_speedDials
->GetItem(item
))
1148 MakeCall(item
.m_text
);
1152 void MyManager::OnSpeedDialColumnResize(wxListEvent
& event
)
1154 wxConfigBase
* config
= wxConfig::Get();
1155 config
->SetPath(AppearanceGroup
);
1157 key
.sprintf("ColumnWidth%u", event
.GetColumn());
1158 config
->Write(key
, m_speedDials
->GetColumnWidth(event
.GetColumn()));
1162 void MyManager::OnRightClick(wxListEvent
& event
)
1164 wxMenuBar
* menuBar
= wxXmlResource::Get()->LoadMenuBar("PopUpMenu");
1165 PopupMenu(menuBar
->GetMenu(0), event
.GetPoint());
1170 void MyManager::EditSpeedDial(int index
)
1176 item
.m_itemId
= index
;
1177 item
.m_mask
= wxLIST_MASK_TEXT
;
1179 item
.m_col
= e_NameColumn
;
1180 if (!m_speedDials
->GetItem(item
))
1183 // Should display a menu, but initially just allow editing
1184 SpeedDialDialog
dlg(this);
1186 wxString originalName
= dlg
.m_Name
= item
.m_text
;
1188 item
.m_col
= e_NumberColumn
;
1189 if (m_speedDials
->GetItem(item
))
1190 dlg
.m_Number
= item
.m_text
;
1192 item
.m_col
= e_AddressColumn
;
1193 if (m_speedDials
->GetItem(item
))
1194 dlg
.m_Address
= item
.m_text
;
1196 item
.m_col
= e_DescriptionColumn
;
1197 if (m_speedDials
->GetItem(item
))
1198 dlg
.m_Description
= item
.m_text
;
1200 if (dlg
.ShowModal() == wxID_OK
) {
1201 item
.m_col
= e_NameColumn
;
1202 item
.m_text
= dlg
.m_Name
;
1203 m_speedDials
->SetItem(item
);
1205 item
.m_col
= e_NumberColumn
;
1206 item
.m_text
= dlg
.m_Number
;
1207 m_speedDials
->SetItem(item
);
1209 item
.m_col
= e_AddressColumn
;
1210 item
.m_text
= dlg
.m_Address
;
1211 m_speedDials
->SetItem(item
);
1213 item
.m_col
= e_DescriptionColumn
;
1214 item
.m_text
= dlg
.m_Description
;
1215 m_speedDials
->SetItem(item
);
1217 wxConfigBase
* config
= wxConfig::Get();
1218 config
->SetPath(SpeedDialsGroup
);
1219 config
->DeleteGroup(originalName
);
1220 config
->SetPath(dlg
.m_Name
);
1221 config
->Write(SpeedDialNumberKey
, dlg
.m_Number
);
1222 config
->Write(SpeedDialAddressKey
, dlg
.m_Address
);
1223 config
->Write(SpeedDialDescriptionKey
, dlg
.m_Description
);
1228 bool MyManager::HasSpeedDialName(const wxString
& name
) const
1230 return m_speedDials
->FindItem(-1, name
) >= 0;
1234 int MyManager::GetSpeedDialIndex(const char * number
, const char * ignore
) const
1236 int count
= m_speedDials
->GetItemCount();
1238 item
.m_mask
= wxLIST_MASK_TEXT
;
1239 item
.m_col
= e_NumberColumn
;
1240 for (item
.m_itemId
= 0; item
.m_itemId
< count
; item
.m_itemId
++) {
1241 if (m_speedDials
->GetItem(item
)) {
1242 int len
= item
.m_text
.Length();
1243 if (len
> 0 && (ignore
== NULL
|| strcmp(ignore
, item
.m_text
) != 0) && strncmp(number
, item
.m_text
, len
) == 0)
1244 return item
.m_itemId
;
1251 void MyManager::MakeCall(const PwxString
& address
)
1253 if (address
.IsEmpty())
1256 SetState(CallingState
);
1258 LogWindow
<< "Calling \"" << address
<< '"' << endl
;
1260 if (potsEP
!= NULL
&& potsEP
->GetLine("*") != NULL
)
1261 SetUpCall("pots:*", address
, m_currentCallToken
);
1263 SetUpCall("pc:*", address
, m_currentCallToken
);
1267 void MyManager::AnswerCall()
1269 if (m_callState
!= RingingState
)
1273 SetState(AnsweringState
);
1274 pcssEP
->AcceptIncomingConnection(m_ringingConnectionToken
);
1278 void MyManager::RejectCall()
1280 if (m_callState
!= RingingState
)
1283 ClearCall(m_currentCallToken
);
1284 SetState(IdleState
);
1288 void MyManager::HangUpCall()
1290 if (m_callState
== IdleState
)
1293 LogWindow
<< "Hanging up \"" << m_currentCallToken
<< '"' << endl
;
1294 ClearCall(m_currentCallToken
);
1295 SetState(IdleState
);
1299 void MyManager::OnRinging(const OpalPCSSConnection
& connection
)
1301 m_ringingConnectionToken
= connection
.GetToken();
1302 m_currentCallToken
= connection
.GetCall().GetToken();
1308 LogWindow
<< "\nIncoming call at " << now
.AsString("w h:mma")
1309 << " from " << connection
.GetRemotePartyName() << endl
;
1311 if (!m_RingSoundFileName
.empty()) {
1312 m_RingSoundChannel
.Open(m_RingSoundDeviceName
, PSoundChannel::Player
);
1313 m_RingSoundChannel
.PlayFile(m_RingSoundFileName
.c_str(), FALSE
);
1314 m_RingSoundTimer
.RunContinuous(5000);
1317 SetState(RingingState
);
1322 void MyManager::OnRingSoundAgain(PTimer
&, INT
)
1324 m_RingSoundChannel
.PlayFile(m_RingSoundFileName
.c_str(), FALSE
);
1328 void MyManager::StopRingSound()
1330 m_RingSoundTimer
.Stop();
1331 m_RingSoundChannel
.Close();
1335 BOOL
MyManager::OnIncomingConnection(OpalConnection
& connection
)
1337 if (connection
.GetEndPoint().GetPrefixName() == "pots")
1338 LogWindow
<< "Line interface device \"" << connection
.GetRemotePartyName() << "\" has gone off hook." << endl
;
1340 return OpalManager::OnIncomingConnection(connection
);
1344 void MyManager::OnEstablishedCall(OpalCall
& call
)
1346 m_currentCallToken
= call
.GetToken();
1347 LogWindow
<< "Established call from " << call
.GetPartyA() << " to " << call
.GetPartyB() << endl
;
1348 SetState(InCallState
);
1352 void MyManager::OnClearedCall(OpalCall
& call
)
1356 PString name
= call
.GetPartyB().IsEmpty() ? call
.GetPartyA() : call
.GetPartyB();
1358 switch (call
.GetCallEndReason()) {
1359 case OpalConnection::EndedByRemoteUser
:
1360 LogWindow
<< '"' << name
<< "\" has cleared the call";
1362 case OpalConnection::EndedByCallerAbort
:
1363 LogWindow
<< '"' << name
<< "\" has stopped calling";
1365 case OpalConnection::EndedByRefusal
:
1366 LogWindow
<< '"' << name
<< "\" did not accept your call";
1368 case OpalConnection::EndedByNoAnswer
:
1369 LogWindow
<< '"' << name
<< "\" did not answer your call";
1371 case OpalConnection::EndedByTransportFail
:
1372 LogWindow
<< "Call with \"" << name
<< "\" ended abnormally";
1374 case OpalConnection::EndedByCapabilityExchange
:
1375 LogWindow
<< "Could not find common codec with \"" << name
<< '"';
1377 case OpalConnection::EndedByNoAccept
:
1378 LogWindow
<< "Did not accept incoming call from \"" << name
<< '"';
1380 case OpalConnection::EndedByAnswerDenied
:
1381 LogWindow
<< "Refused incoming call from \"" << name
<< '"';
1383 case OpalConnection::EndedByNoUser
:
1384 LogWindow
<< "Gatekeeper could find user \"" << name
<< '"';
1386 case OpalConnection::EndedByNoBandwidth
:
1387 LogWindow
<< "Call to \"" << name
<< "\" aborted, insufficient bandwidth.";
1389 case OpalConnection::EndedByUnreachable
:
1390 LogWindow
<< '"' << name
<< "\" could not be reached.";
1392 case OpalConnection::EndedByNoEndPoint
:
1393 LogWindow
<< "No phone running for \"" << name
<< '"';
1395 case OpalConnection::EndedByHostOffline
:
1396 LogWindow
<< '"' << name
<< "\" is not online.";
1398 case OpalConnection::EndedByConnectFail
:
1399 LogWindow
<< "Transport error calling \"" << name
<< '"';
1402 LogWindow
<< "Call with \"" << name
<< "\" completed";
1405 LogWindow
<< ", on " << now
.AsString("w h:mma") << ". Duration "
1406 << setprecision(0) << setw(5) << (now
- call
.GetStartTime())
1409 SetState(IdleState
);
1413 BOOL
MyManager::OnOpenMediaStream(OpalConnection
& connection
, OpalMediaStream
& stream
)
1415 if (!OpalManager::OnOpenMediaStream(connection
, stream
))
1418 PString prefix
= connection
.GetEndPoint().GetPrefixName();
1419 if (prefix
== pcssEP
->GetPrefixName())
1422 LogWindow
<< "Started ";
1424 if (stream
.IsSource())
1425 LogWindow
<< "receiving ";
1427 LogWindow
<< "sending ";
1429 LogWindow
<< stream
.GetMediaFormat();
1431 if (stream
.IsSource())
1432 LogWindow
<< " from ";
1434 LogWindow
<< " to ";
1436 LogWindow
<< connection
.GetEndPoint().GetPrefixName() << " endpoint" << endl
;
1442 PSafePtr
<OpalConnection
> MyManager::GetUserConnection()
1444 PSafePtr
<OpalCall
> call
= GetCall();
1448 for (int i
= 0; ; i
++) {
1449 PSafePtr
<OpalConnection
> connection
= call
->GetConnection(0);
1450 if (connection
== NULL
)
1453 if (PIsDescendant(&(*connection
), OpalPCSSConnection
) || PIsDescendant(&(*connection
), OpalLineConnection
))
1461 void MyManager::SendUserInput(char tone
)
1463 PSafePtr
<OpalConnection
> connection
= GetUserConnection();
1464 if (connection
!= NULL
)
1465 connection
->OnUserInputTone(tone
, 100);
1469 BOOL
MyManager::CreateVideoOutputDevice(const OpalConnection
& connection
,
1470 const OpalMediaFormat
& mediaFormat
,
1472 PVideoOutputDevice
* & device
,
1475 if (preview
&& !m_VideoGrabPreview
)
1478 // We ALWAYS use a Window
1479 device
= PVideoOutputDevice::CreateDevice("Window");
1480 if (device
!= NULL
) {
1483 #if defined(__WXMSW__)
1484 name
.sprintf("MSWIN STYLE=0x%08X ", WS_POPUP
|WS_BORDER
|WS_SYSMENU
|WS_CAPTION
);
1487 name
+= preview
? "Local" : (const char *)connection
.GetRemotePartyName();
1489 if (device
->Open(name
))
1495 return OpalManager::CreateVideoOutputDevice(connection
, mediaFormat
, preview
, device
, autoDelete
);
1499 void MyManager::OnUserInputString(OpalConnection
& connection
, const PString
& value
)
1501 LogWindow
<< "User input \"" << value
<< "\" received from \"" << connection
.GetRemotePartyName() << '"' << endl
;
1502 OpalManager::OnUserInputString(connection
, value
);
1506 PString
MyManager::ReadUserInput(OpalConnection
& connection
,
1507 const char * terminators
,
1509 unsigned firstDigitTimeout
)
1511 // The usual behaviour is to read until a '#' or timeout and that yields the
1512 // entire destination address. However for this application we want to disable
1513 // the timeout and short circuit the need for '#' as the speed dial number is
1516 PTRACE(3, "OpalPhone\tReadUserInput from " << connection
);
1518 connection
.PromptUserInput(TRUE
);
1519 PString digit
= connection
.GetUserInput(firstDigitTimeout
);
1520 connection
.PromptUserInput(FALSE
);
1523 while (!digit
.IsEmpty()) {
1526 int index
= GetSpeedDialIndex(input
, NULL
);
1528 wxListItem nameItem
;
1529 nameItem
.m_itemId
= index
;
1530 nameItem
.m_mask
= wxLIST_MASK_TEXT
;
1531 nameItem
.m_col
= e_NameColumn
;
1532 wxListItem addressItem
= nameItem
;
1533 addressItem
.m_col
= e_AddressColumn
;
1534 if (m_speedDials
->GetItem(nameItem
) && m_speedDials
->GetItem(addressItem
)) {
1535 LogWindow
<< "Calling \"" << nameItem
.m_text
<< "\" using \"" << addressItem
.m_text
<< '"' << endl
;
1536 return addressItem
.m_text
.c_str();
1540 digit
= connection
.GetUserInput(firstDigitTimeout
);
1543 PTRACE(2, "OpalPhone\tReadUserInput timeout (" << firstDigitTimeout
<< "ms) on " << *this);
1544 return PString::Empty();
1548 void MyManager::SetState(CallState newState
)
1550 if (m_callState
== newState
)
1553 m_callState
= newState
;
1555 m_speedDials
->Show(newState
== IdleState
);
1556 m_answerPanel
->Show(newState
== RingingState
);
1557 m_callingPanel
->Show(newState
== CallingState
);
1558 m_inCallPanel
->Show(newState
== InCallState
);
1560 wxWindow
* newWindow
;
1563 newWindow
= m_answerPanel
;
1567 newWindow
= m_inCallPanel
;
1571 newWindow
= m_callingPanel
;
1575 newWindow
= m_speedDials
;
1578 m_splitter
->ReplaceWindow(m_splitter
->GetWindow1(), newWindow
);
1582 bool MyManager::StartGatekeeper()
1584 if (m_gatekeeperMode
== 0)
1585 h323EP
->RemoveGatekeeper();
1587 LogWindow
<< "H.323 registration started for " << m_gatekeeperIdentifier
;
1588 if (!m_gatekeeperIdentifier
.IsEmpty() || !m_gatekeeperAddress
.IsEmpty())
1590 LogWindow
<< m_gatekeeperAddress
<< endl
;
1592 if (h323EP
->UseGatekeeper(m_gatekeeperAddress
, m_gatekeeperIdentifier
)) {
1593 LogWindow
<< "H.323 registration successful to " << *h323EP
->GetGatekeeper() << endl
;
1598 return m_gatekeeperMode
< 2;
1602 bool MyManager::StartRegistrar()
1604 if (m_registrarUsed
) {
1605 if (!sipEP
->Register(m_registrarName
, m_registrarUser
, m_registrarUser
, m_registrarPassword
))
1608 LogWindow
<< "SIP registration started for " << m_registrarUser
<< '@' << m_registrarName
<< endl
;
1611 PString aor
= m_registrarUser
+ '@' + m_registrarName
;
1612 if (sipEP
->IsRegistered(aor
)) {
1613 LogWindow
<< "SIP registration ended for " << aor
<< endl
;
1614 sipEP
->Unregister(aor
);
1621 void MyManager::InitMediaInfo(const char * source
, const OpalMediaFormatList
& mediaFormats
)
1623 for (PINDEX i
= 0; i
< mediaFormats
.GetSize(); i
++) {
1624 const OpalMediaFormat
& mediaFormat
= mediaFormats
[i
];
1625 if (mediaFormat
.GetPayloadType() != RTP_DataFrame::MaxPayloadType
)
1626 m_mediaInfo
.push_back(MyMedia(source
, mediaFormat
));
1631 void MyManager::ApplyMediaInfo()
1633 PStringList mediaFormatOrder
, mediaFormatMask
;
1637 for (MyMediaList::iterator mm
= m_mediaInfo
.begin(); mm
!= m_mediaInfo
.end(); ++mm
) {
1638 if (mm
->preferenceOrder
< 0)
1639 mediaFormatMask
.AppendString(mm
->mediaFormat
);
1641 mediaFormatOrder
.AppendString(mm
->mediaFormat
);
1644 if (!mediaFormatOrder
.IsEmpty()) {
1645 SetMediaFormatOrder(mediaFormatOrder
);
1646 SetMediaFormatMask(mediaFormatMask
);
1651 ///////////////////////////////////////////////////////////////////////////////
1653 void MyManager::OnOptions(wxCommandEvent
& /*event*/)
1655 OptionsDialog
dlg(this);
1659 BEGIN_EVENT_TABLE(OptionsDialog
, wxDialog
)
1660 ////////////////////////////////////////
1661 // Networking fields
1662 EVT_CHOICE(XRCID("BandwidthClass"), OptionsDialog::BandwidthClass
)
1663 EVT_LISTBOX(XRCID("LocalInterfaces"), OptionsDialog::SelectedLocalInterface
)
1664 EVT_TEXT(XRCID("InterfaceToAdd"), OptionsDialog::ChangedInterfaceToAdd
)
1665 EVT_BUTTON(XRCID("AddInterface"), OptionsDialog::AddInterface
)
1666 EVT_BUTTON(XRCID("RemoveInterface"), OptionsDialog::RemoveInterface
)
1668 ////////////////////////////////////////
1670 EVT_COMBOBOX(XRCID(LineInterfaceDeviceKey
), OptionsDialog::SelectedLID
)
1672 ////////////////////////////////////////
1674 EVT_BUTTON(XRCID("BrowseSoundFile"), OptionsDialog::BrowseSoundFile
)
1675 EVT_BUTTON(XRCID("PlaySoundFile"), OptionsDialog::PlaySoundFile
)
1676 EVT_BUTTON(XRCID("AddCodec"), OptionsDialog::AddCodec
)
1677 EVT_BUTTON(XRCID("RemoveCodec"), OptionsDialog::RemoveCodec
)
1678 EVT_BUTTON(XRCID("MoveUpCodec"), OptionsDialog::MoveUpCodec
)
1679 EVT_BUTTON(XRCID("MoveDownCodec"), OptionsDialog::MoveDownCodec
)
1680 EVT_LISTBOX(XRCID("AllCodecs"), OptionsDialog::SelectedCodecToAdd
)
1681 EVT_LISTBOX(XRCID("SelectedCodecs"), OptionsDialog::SelectedCodec
)
1682 EVT_LIST_ITEM_SELECTED(XRCID("CodecOptionsList"), OptionsDialog::SelectedCodecOption
)
1683 EVT_LIST_ITEM_DESELECTED(XRCID("CodecOptionsList"), OptionsDialog::DeselectedCodecOption
)
1684 EVT_TEXT(XRCID("CodecOptionValue"), OptionsDialog::ChangedCodecOptionValue
)
1686 ////////////////////////////////////////
1688 EVT_BUTTON(XRCID("AddRoute"), OptionsDialog::AddRoute
)
1689 EVT_BUTTON(XRCID("RemoveRoute"), OptionsDialog::RemoveRoute
)
1690 EVT_LIST_ITEM_SELECTED(XRCID("Routes"), OptionsDialog::SelectedRoute
)
1691 EVT_LIST_ITEM_DESELECTED(XRCID("Routes"), OptionsDialog::DeselectedRoute
)
1692 EVT_TEXT(XRCID("RoutePattern"), OptionsDialog::ChangedRouteInfo
)
1693 EVT_TEXT(XRCID("RouteDestination"), OptionsDialog::ChangedRouteInfo
)
1695 ////////////////////////////////////////
1697 EVT_LISTBOX(XRCID("Aliases"), OptionsDialog::SelectedAlias
)
1698 EVT_BUTTON(XRCID("AddAlias"), OptionsDialog::AddAlias
)
1699 EVT_BUTTON(XRCID("RemoveAlias"), OptionsDialog::RemoveAlias
)
1700 EVT_TEXT(XRCID("NewAlias"), OptionsDialog::ChangedNewAlias
)
1704 #define INIT_FIELD(name, value) \
1706 FindWindowByName(name##Key)->SetValidator(wxGenericValidator(&m_##name))
1708 OptionsDialog::OptionsDialog(MyManager
* manager
)
1709 : m_manager(*manager
)
1713 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY
);
1714 wxXmlResource::Get()->LoadDialog(this, manager
, "OptionsDialog");
1716 ////////////////////////////////////////
1718 INIT_FIELD(Username
, m_manager
.GetDefaultUserName());
1719 INIT_FIELD(DisplayName
, m_manager
.GetDefaultDisplayName());
1721 PStringList devices
= PSoundChannel::GetDeviceNames(PSoundChannel::Player
);
1722 wxChoice
* choice
= FindWindowByNameAs
<wxChoice
>(this, RingSoundDeviceNameKey
);
1723 choice
->SetValidator(wxGenericValidator(&m_RingSoundDeviceName
));
1724 for (i
= 0; i
< devices
.GetSize(); i
++)
1725 choice
->Append((const char *)devices
[i
]);
1726 m_RingSoundDeviceName
= m_manager
.m_RingSoundDeviceName
;
1727 INIT_FIELD(RingSoundFileName
, m_manager
.m_RingSoundFileName
);
1729 INIT_FIELD(AutoAnswer
, m_manager
.m_autoAnswer
);
1731 INIT_FIELD(IVRScript
, m_manager
.ivrEP
->GetDefaultVXML());
1734 ////////////////////////////////////////
1735 // Networking fields
1736 int bandwidth
= m_manager
.h323EP
->GetInitialBandwidth();
1737 m_Bandwidth
.sprintf(bandwidth
%10 == 0 ? "%u" : "%u.%u", bandwidth
/10, bandwidth
%10);
1738 FindWindowByName(BandwidthKey
)->SetValidator(wxTextValidator(wxFILTER_NUMERIC
, &m_Bandwidth
));
1740 if (bandwidth
<= 144)
1742 else if (bandwidth
<= 288)
1744 else if (bandwidth
<= 640)
1746 else if (bandwidth
<= 1280)
1748 else if (bandwidth
<= 15000)
1752 FindWindowByNameAs
<wxChoice
>(this, "BandwidthClass")->SetSelection(bandwidthClass
);
1754 INIT_FIELD(TCPPortBase
, m_manager
.GetTCPPortBase());
1755 INIT_FIELD(TCPPortMax
, m_manager
.GetTCPPortMax());
1756 INIT_FIELD(UDPPortBase
, m_manager
.GetUDPPortBase());
1757 INIT_FIELD(UDPPortMax
, m_manager
.GetUDPPortMax());
1758 INIT_FIELD(RTPPortBase
, m_manager
.GetRtpIpPortBase());
1759 INIT_FIELD(RTPPortMax
, m_manager
.GetRtpIpPortMax());
1760 INIT_FIELD(RTPTOS
, m_manager
.GetRtpIpTypeofService());
1761 INIT_FIELD(STUNServer
, m_manager
.GetSTUN() != NULL
? m_manager
.GetSTUN()->GetServer() : PString());
1762 PwxString natRouter
;
1763 if (m_manager
.GetTranslationAddress().IsValid())
1764 natRouter
= m_manager
.GetTranslationAddress().AsString();
1765 INIT_FIELD(NATRouter
, natRouter
);
1767 m_AddInterface
= FindWindowByNameAs
<wxButton
>(this, "AddInterface");
1768 m_AddInterface
->Disable();
1769 m_RemoveInterface
= FindWindowByNameAs
<wxButton
>(this, "RemoveInterface");
1770 m_RemoveInterface
->Disable();
1771 m_InterfaceToAdd
= FindWindowByNameAs
<wxTextCtrl
>(this, "InterfaceToAdd");
1772 m_LocalInterfaces
= FindWindowByNameAs
<wxListBox
>(this, "LocalInterfaces");
1773 for (i
= 0; i
< m_manager
.m_LocalInterfaces
.GetSize(); i
++)
1774 m_LocalInterfaces
->Append((const char *)m_manager
.m_LocalInterfaces
[i
]);
1776 ////////////////////////////////////////
1778 INIT_FIELD(SoundBuffers
, m_manager
.pcssEP
->GetSoundChannelBufferDepth());
1779 INIT_FIELD(MinJitter
, m_manager
.GetMinAudioJitterDelay());
1780 INIT_FIELD(MaxJitter
, m_manager
.GetMaxAudioJitterDelay());
1781 INIT_FIELD(SilenceSuppression
, m_manager
.GetSilenceDetectParams().m_mode
);
1782 INIT_FIELD(SilenceThreshold
, m_manager
.GetSilenceDetectParams().m_threshold
);
1783 INIT_FIELD(SignalDeadband
, m_manager
.GetSilenceDetectParams().m_signalDeadband
/8);
1784 INIT_FIELD(SilenceDeadband
, m_manager
.GetSilenceDetectParams().m_silenceDeadband
/8);
1786 // Fill sound player combo box with available devices and set selection
1787 wxComboBox
* combo
= FindWindowByNameAs
<wxComboBox
>(this, SoundPlayerKey
);
1788 combo
->SetValidator(wxGenericValidator(&m_SoundPlayer
));
1789 for (i
= 0; i
< devices
.GetSize(); i
++)
1790 combo
->Append((const char *)devices
[i
]);
1791 m_SoundPlayer
= m_manager
.pcssEP
->GetSoundChannelPlayDevice();
1793 // Fill sound recorder combo box with available devices and set selection
1794 combo
= FindWindowByNameAs
<wxComboBox
>(this, SoundRecorderKey
);
1795 combo
->SetValidator(wxGenericValidator(&m_SoundRecorder
));
1796 devices
= PSoundChannel::GetDeviceNames(PSoundChannel::Recorder
);
1797 for (i
= 0; i
< devices
.GetSize(); i
++)
1798 combo
->Append((const char *)devices
[i
]);
1799 m_SoundRecorder
= m_manager
.pcssEP
->GetSoundChannelRecordDevice();
1801 // Fill line interface combo box with available devices and set selection
1802 m_selectedAEC
= FindWindowByNameAs
<wxChoice
>(this, AECKey
);
1803 m_selectedCountry
= FindWindowByNameAs
<wxComboBox
>(this, CountryKey
);
1804 m_selectedCountry
->SetValidator(wxGenericValidator(&m_Country
));
1805 m_selectedLID
= FindWindowByNameAs
<wxComboBox
>(this, LineInterfaceDeviceKey
);
1806 m_selectedLID
->SetValidator(wxGenericValidator(&m_LineInterfaceDevice
));
1807 devices
= OpalLineInterfaceDevice::GetAllDevices();
1808 if (devices
.IsEmpty()) {
1809 m_LineInterfaceDevice
= "<< None available >>";
1810 m_selectedLID
->Append(m_LineInterfaceDevice
);
1811 m_selectedAEC
->Disable();
1812 m_selectedCountry
->Disable();
1815 static const char UseSoundCard
[] = "<< Use sound card only >>";
1816 m_selectedLID
->Append(UseSoundCard
);
1817 for (i
= 0; i
< devices
.GetSize(); i
++)
1818 m_selectedLID
->Append((const char *)devices
[i
]);
1820 OpalLine
* line
= m_manager
.potsEP
->GetLine("*");
1822 m_LineInterfaceDevice
= line
->GetDevice().GetDeviceType() + ": " + line
->GetDevice().GetDeviceName();
1823 for (i
= 0; i
< devices
.GetSize(); i
++) {
1824 if (m_LineInterfaceDevice
== devices
[i
])
1827 if (i
>= devices
.GetSize()) {
1828 for (i
= 0; i
< devices
.GetSize(); i
++) {
1829 if (devices
[i
].Find(m_LineInterfaceDevice
.c_str()) == 0)
1832 if (i
>= devices
.GetSize())
1833 m_LineInterfaceDevice
= devices
[0];
1836 INIT_FIELD(AEC
, line
->GetAEC());
1838 PStringList countries
= line
->GetDevice().GetCountryCodeNameList();
1839 for (i
= 0; i
< countries
.GetSize(); i
++)
1840 m_selectedCountry
->Append((const char *)countries
[i
]);
1841 INIT_FIELD(Country
, line
->GetDevice().GetCountryCodeName());
1844 m_LineInterfaceDevice
= UseSoundCard
;
1845 m_selectedAEC
->Disable();
1846 m_selectedCountry
->Disable();
1850 ////////////////////////////////////////
1852 INIT_FIELD(VideoGrabber
, m_manager
.GetVideoInputDevice().deviceName
);
1853 INIT_FIELD(VideoGrabFormat
, m_manager
.GetVideoInputDevice().videoFormat
);
1854 INIT_FIELD(VideoGrabSource
, m_manager
.GetVideoInputDevice().channelNumber
);
1855 INIT_FIELD(VideoGrabFrameRate
, m_manager
.GetVideoInputDevice().rate
);
1856 INIT_FIELD(VideoFlipLocal
, m_manager
.GetVideoInputDevice().flip
!= FALSE
);
1857 INIT_FIELD(VideoGrabPreview
, m_manager
.m_VideoGrabPreview
);
1858 INIT_FIELD(VideoAutoTransmit
, m_manager
.CanAutoStartTransmitVideo() != FALSE
);
1859 INIT_FIELD(VideoAutoReceive
, m_manager
.CanAutoStartReceiveVideo() != FALSE
);
1860 INIT_FIELD(VideoFlipRemote
, m_manager
.GetVideoOutputDevice().flip
!= FALSE
);
1862 choice
= FindWindowByNameAs
<wxChoice
>(this, "VideoGrabber");
1863 devices
= PVideoInputDevice::GetDriversDeviceNames("*");
1864 for (i
= 0; i
< devices
.GetSize(); i
++)
1865 choice
->Append((const char *)devices
[i
]);
1867 ////////////////////////////////////////
1869 m_AddCodec
= FindWindowByNameAs
<wxButton
>(this, "AddCodec");
1870 m_AddCodec
->Disable();
1871 m_RemoveCodec
= FindWindowByNameAs
<wxButton
>(this, "RemoveCodec");
1872 m_RemoveCodec
->Disable();
1873 m_MoveUpCodec
= FindWindowByNameAs
<wxButton
>(this, "MoveUpCodec");
1874 m_MoveUpCodec
->Disable();
1875 m_MoveDownCodec
= FindWindowByNameAs
<wxButton
>(this, "MoveDownCodec");
1876 m_MoveDownCodec
->Disable();
1878 m_allCodecs
= FindWindowByNameAs
<wxListBox
>(this, "AllCodecs");
1879 m_selectedCodecs
= FindWindowByNameAs
<wxListBox
>(this, "SelectedCodecs");
1880 for (MyMediaList::iterator mm
= m_manager
.m_mediaInfo
.begin(); mm
!= m_manager
.m_mediaInfo
.end(); ++mm
) {
1881 wxString str
= mm
->sourceProtocol
;
1883 str
+= (const char *)mm
->mediaFormat
;
1884 m_allCodecs
->Append(str
, &*mm
);
1886 str
= (const char *)mm
->mediaFormat
;
1887 if (mm
->preferenceOrder
>= 0 && m_selectedCodecs
->FindString(str
) < 0)
1888 m_selectedCodecs
->Append(str
, &*mm
);
1890 m_codecOptions
= FindWindowByNameAs
<wxListCtrl
>(this, "CodecOptionsList");
1891 int columnWidth
= (m_codecOptions
->GetClientSize().GetWidth()-30)/2;
1892 m_codecOptions
->InsertColumn(0, "Option", wxLIST_FORMAT_LEFT
, columnWidth
);
1893 m_codecOptions
->InsertColumn(1, "Value", wxLIST_FORMAT_LEFT
, columnWidth
);
1894 m_codecOptionValue
= FindWindowByNameAs
<wxTextCtrl
>(this, "CodecOptionValue");
1895 m_codecOptionValue
->Disable();
1897 ////////////////////////////////////////
1899 m_AddAlias
= FindWindowByNameAs
<wxButton
>(this, "AddAlias");
1900 m_AddAlias
->Disable();
1901 m_RemoveAlias
= FindWindowByNameAs
<wxButton
>(this, "RemoveAlias");
1902 m_RemoveAlias
->Disable();
1903 m_NewAlias
= FindWindowByNameAs
<wxTextCtrl
>(this, "NewAlias");
1904 m_Aliases
= FindWindowByNameAs
<wxListBox
>(this, "Aliases");
1905 PStringList aliases
= m_manager
.h323EP
->GetAliasNames();
1906 for (i
= 1; i
< aliases
.GetSize(); i
++)
1907 m_Aliases
->Append((const char *)aliases
[i
]);
1909 INIT_FIELD(DTMFSendMode
, m_manager
.h323EP
->GetSendUserInputMode());
1910 INIT_FIELD(CallIntrusionProtectionLevel
, m_manager
.h323EP
->GetCallIntrusionProtectionLevel());
1911 INIT_FIELD(DisableFastStart
, m_manager
.h323EP
->IsFastStartDisabled() != FALSE
);
1912 INIT_FIELD(DisableH245Tunneling
, m_manager
.h323EP
->IsH245TunnelingDisabled() != FALSE
);
1913 INIT_FIELD(DisableH245inSETUP
, m_manager
.h323EP
->IsH245inSetupDisabled() != FALSE
);
1914 INIT_FIELD(GatekeeperMode
, m_manager
.m_gatekeeperMode
);
1915 INIT_FIELD(GatekeeperAddress
, m_manager
.m_gatekeeperAddress
);
1916 INIT_FIELD(GatekeeperIdentifier
, m_manager
.m_gatekeeperIdentifier
);
1917 INIT_FIELD(GatekeeperTTL
, m_manager
.h323EP
->GetGatekeeperTimeToLive().GetSeconds());
1918 INIT_FIELD(GatekeeperLogin
, m_manager
.h323EP
->GetGatekeeperUsername());
1919 INIT_FIELD(GatekeeperPassword
, m_manager
.h323EP
->GetGatekeeperPassword());
1921 ////////////////////////////////////////
1923 INIT_FIELD(SIPProxyUsed
, m_manager
.m_SIPProxyUsed
);
1924 INIT_FIELD(SIPProxy
, m_manager
.sipEP
->GetProxy().GetHostName());
1925 INIT_FIELD(SIPProxyUsername
, m_manager
.sipEP
->GetProxy().GetUserName());
1926 INIT_FIELD(SIPProxyPassword
, m_manager
.sipEP
->GetProxy().GetPassword());
1927 INIT_FIELD(RegistrarUsed
, m_manager
.m_registrarUsed
);
1928 INIT_FIELD(RegistrarName
, m_manager
.m_registrarName
);
1929 INIT_FIELD(RegistrarUsername
, m_manager
.m_registrarUser
);
1930 INIT_FIELD(RegistrarPassword
, m_manager
.m_registrarPassword
);
1931 INIT_FIELD(RegistrarTimeToLive
, m_manager
.sipEP
->GetRegistrarTimeToLive().GetSeconds());
1933 ////////////////////////////////////////
1935 m_SelectedRoute
= INT_MAX
;
1937 m_RoutePattern
= FindWindowByNameAs
<wxTextCtrl
>(this, "RoutePattern");
1938 m_RouteDestination
= FindWindowByNameAs
<wxTextCtrl
>(this, "RouteDestination");
1940 m_AddRoute
= FindWindowByNameAs
<wxButton
>(this, "AddRoute");
1941 m_AddRoute
->Disable();
1943 m_RemoveRoute
= FindWindowByNameAs
<wxButton
>(this, "RemoveRoute");
1944 m_RemoveRoute
->Disable();
1946 // Fill list box with active routes
1947 static char const AllSources
[] = "<ALL>";
1948 m_Routes
= FindWindowByNameAs
<wxListCtrl
>(this, "Routes");
1949 m_Routes
->InsertColumn(0, _T("Source"));
1950 m_Routes
->InsertColumn(1, _T("Pattern"));
1951 m_Routes
->InsertColumn(2, _T("Destination"));
1952 const OpalManager::RouteTable
& routeTable
= m_manager
.GetRouteTable();
1953 for (i
= 0; i
< routeTable
.GetSize(); i
++) {
1954 PString pattern
= routeTable
[i
].pattern
;
1955 PINDEX colon
= pattern
.Find(':');
1957 if (colon
== P_MAX_INDEX
) {
1958 source
= AllSources
;
1962 source
= (const char *)pattern
.Left(colon
);
1964 source
= AllSources
;
1967 int pos
= m_Routes
->InsertItem(INT_MAX
, source
);
1968 m_Routes
->SetItem(pos
, 1, (const char *)pattern
.Mid(colon
));
1969 m_Routes
->SetItem(pos
, 2, (const char *)routeTable
[i
].destination
);
1972 // Fill combo box with possible protocols
1973 m_RouteSource
= FindWindowByNameAs
<wxComboBox
>(this, "RouteSource");
1974 m_RouteSource
->Append(AllSources
);
1975 const PList
<OpalEndPoint
> & endponts
= m_manager
.GetEndPoints();
1976 for (i
= 0; i
< endponts
.GetSize(); i
++)
1977 m_RouteSource
->Append((const char *)endponts
[i
].GetPrefixName());
1978 m_RouteSource
->SetSelection(0);
1982 ////////////////////////////////////////
1984 INIT_FIELD(EnableTracing
, m_manager
.m_enableTracing
);
1985 INIT_FIELD(TraceLevelThreshold
, PTrace::GetLevel());
1986 INIT_FIELD(TraceLevelNumber
, (PTrace::GetOptions()&PTrace::TraceLevel
) != 0);
1987 INIT_FIELD(TraceFileLine
, (PTrace::GetOptions()&PTrace::FileAndLine
) != 0);
1988 INIT_FIELD(TraceBlocks
, (PTrace::GetOptions()&PTrace::Blocks
) != 0);
1989 INIT_FIELD(TraceDateTime
, (PTrace::GetOptions()&PTrace::DateAndTime
) != 0);
1990 INIT_FIELD(TraceTimestamp
, (PTrace::GetOptions()&PTrace::Timestamp
) != 0);
1991 INIT_FIELD(TraceThreadName
, (PTrace::GetOptions()&PTrace::Thread
) != 0);
1992 INIT_FIELD(TraceThreadAddress
, (PTrace::GetOptions()&PTrace::ThreadAddress
) != 0);
1993 INIT_FIELD(TraceFileName
, m_manager
.m_traceFileName
);
1995 wxNotebook
* book
= FindWindowByNameAs
<wxNotebook
>(this, "OptionsNotebook");
1996 book
->DeletePage(book
->GetPageCount()-1);
2001 #define SAVE_FIELD(name, set) \
2003 config->Write(name##Key, m_##name)
2005 #define SAVE_FIELD2(name1, name2, set) \
2006 set(m_##name1, m_##name2); \
2007 config->Write(name1##Key, m_##name1); \
2008 config->Write(name2##Key, m_##name2)
2010 bool OptionsDialog::TransferDataFromWindow()
2012 if (!wxDialog::TransferDataFromWindow())
2015 double floatBandwidth
;
2016 if (!m_Bandwidth
.ToDouble(&floatBandwidth
) || floatBandwidth
< 10)
2019 ::wxBeginBusyCursor();
2021 wxConfigBase
* config
= wxConfig::Get();
2023 ////////////////////////////////////////
2025 config
->SetPath(GeneralGroup
);
2026 SAVE_FIELD(Username
, m_manager
.SetDefaultUserName
);
2027 SAVE_FIELD(DisplayName
, m_manager
.SetDefaultDisplayName
);
2028 SAVE_FIELD(RingSoundDeviceName
, m_manager
.m_RingSoundDeviceName
= );
2029 SAVE_FIELD(RingSoundFileName
, m_manager
.m_RingSoundFileName
= );
2030 SAVE_FIELD(AutoAnswer
, m_manager
.m_autoAnswer
= );
2032 SAVE_FIELD(IVRScript
, m_manager
.ivrEP
->SetDefaultVXML
);
2035 ////////////////////////////////////////
2036 // Networking fields
2037 config
->SetPath(NetworkingGroup
);
2038 int adjustedBandwidth
= (int)(floatBandwidth
*10);
2039 m_manager
.h323EP
->SetInitialBandwidth(adjustedBandwidth
);
2040 config
->Write(BandwidthKey
, adjustedBandwidth
);
2041 SAVE_FIELD2(TCPPortBase
, TCPPortMax
, m_manager
.SetTCPPorts
);
2042 SAVE_FIELD2(UDPPortBase
, UDPPortMax
, m_manager
.SetUDPPorts
);
2043 SAVE_FIELD2(RTPPortBase
, RTPPortMax
, m_manager
.SetRtpIpPorts
);
2044 SAVE_FIELD(RTPTOS
, m_manager
.SetRtpIpTypeofService
);
2045 SAVE_FIELD(STUNServer
, m_manager
.SetSTUNServer
);
2046 SAVE_FIELD(NATRouter
, m_manager
.SetTranslationAddress
);
2048 config
->DeleteGroup(LocalInterfacesGroup
);
2049 config
->SetPath(LocalInterfacesGroup
);
2050 PStringArray
newInterfaces(m_LocalInterfaces
->GetCount());
2051 bool changed
= m_manager
.m_LocalInterfaces
.GetSize() != newInterfaces
.GetSize();
2052 for (int i
= 0; i
< newInterfaces
.GetSize(); i
++) {
2053 newInterfaces
[i
] = m_LocalInterfaces
->GetString(i
);
2054 if (newInterfaces
[i
] != m_manager
.m_LocalInterfaces
)
2057 key
.sprintf("%u", i
+1);
2058 config
->Write(key
, (const char *)newInterfaces
[i
]);
2061 m_manager
.m_LocalInterfaces
= newInterfaces
;
2062 m_manager
.StartAllListeners();
2065 ////////////////////////////////////////
2067 config
->SetPath(AudioGroup
);
2068 SAVE_FIELD(SoundPlayer
, m_manager
.pcssEP
->SetSoundChannelPlayDevice
);
2069 SAVE_FIELD(SoundRecorder
, m_manager
.pcssEP
->SetSoundChannelRecordDevice
);
2070 SAVE_FIELD(SoundBuffers
, m_manager
.pcssEP
->SetSoundChannelBufferDepth
);
2071 SAVE_FIELD2(MinJitter
, MaxJitter
, m_manager
.SetAudioJitterDelay
);
2073 OpalSilenceDetector::Params silenceParams
;
2074 SAVE_FIELD(SilenceSuppression
, silenceParams
.m_mode
=(OpalSilenceDetector::Mode
));
2075 SAVE_FIELD(SilenceThreshold
, silenceParams
.m_threshold
=);
2076 SAVE_FIELD(SignalDeadband
, silenceParams
.m_signalDeadband
=8*);
2077 SAVE_FIELD(SilenceDeadband
, silenceParams
.m_silenceDeadband
=8*);
2078 m_manager
.SetSilenceDetectParams(silenceParams
);
2080 config
->Write(LineInterfaceDeviceKey
, m_LineInterfaceDevice
);
2081 if (m_manager
.potsEP
->AddDeviceName(m_LineInterfaceDevice
)) {
2082 OpalLine
* line
= m_manager
.potsEP
->GetLine("*");
2083 if (PAssertNULL(line
) != NULL
) {
2084 line
->SetAEC((OpalLineInterfaceDevice::AECLevels
)m_AEC
);
2085 config
->Write(AECKey
, m_AEC
);
2086 if (!line
->GetDevice().SetCountryCodeName(m_Country
))
2087 LogWindow
<< "Could not configure Line Interface Device to country \"" << m_Country
<< '"' << endl
;
2088 config
->Write(CountryKey
, m_Country
);
2092 ////////////////////////////////////////
2094 config
->SetPath(VideoGroup
);
2095 PVideoDevice::OpenArgs grabber
= m_manager
.GetVideoInputDevice();
2096 SAVE_FIELD(VideoGrabber
, grabber
.deviceName
= (const char *));
2097 SAVE_FIELD(VideoGrabFormat
, grabber
.videoFormat
= (PVideoDevice::VideoFormat
));
2098 SAVE_FIELD(VideoGrabSource
, grabber
.channelNumber
= );
2099 SAVE_FIELD(VideoGrabFrameRate
, grabber
.rate
= );
2100 SAVE_FIELD(VideoFlipLocal
, grabber
.flip
= );
2101 m_manager
.SetVideoInputDevice(grabber
);
2102 SAVE_FIELD(VideoGrabPreview
, m_manager
.m_VideoGrabPreview
= );
2103 SAVE_FIELD(VideoAutoTransmit
, m_manager
.SetAutoStartTransmitVideo
);
2104 SAVE_FIELD(VideoAutoReceive
, m_manager
.SetAutoStartReceiveVideo
);
2105 // SAVE_FIELD(VideoFlipRemote, );
2107 ////////////////////////////////////////
2109 MyMediaList::iterator mm
;
2110 for (mm
= m_manager
.m_mediaInfo
.begin(); mm
!= m_manager
.m_mediaInfo
.end(); ++mm
)
2111 mm
->preferenceOrder
= -1;
2114 for (codecIndex
= 0; codecIndex
< m_selectedCodecs
->GetCount(); codecIndex
++) {
2115 PwxString selectedFormat
= m_selectedCodecs
->GetString(codecIndex
);
2116 for (mm
= m_manager
.m_mediaInfo
.begin(); mm
!= m_manager
.m_mediaInfo
.end(); ++mm
) {
2117 if (selectedFormat
== mm
->mediaFormat
) {
2118 mm
->preferenceOrder
= codecIndex
;
2124 m_manager
.ApplyMediaInfo();
2126 config
->DeleteGroup(CodecsGroup
);
2127 for (mm
= m_manager
.m_mediaInfo
.begin(); mm
!= m_manager
.m_mediaInfo
.end(); ++mm
) {
2128 if (mm
->preferenceOrder
>= 0) {
2130 groupName
.sprintf("%s/%04u", CodecsGroup
, mm
->preferenceOrder
);
2131 config
->SetPath(groupName
);
2132 config
->Write(CodecNameKey
, (const char *)mm
->mediaFormat
);
2133 for (PINDEX i
= 0; i
< mm
->mediaFormat
.GetOptionCount(); i
++) {
2134 const OpalMediaOption
& option
= mm
->mediaFormat
.GetOption(i
);
2135 if (!option
.IsReadOnly())
2136 config
->Write(PwxString(option
.GetName()), PwxString(option
.AsString()));
2139 OpalMediaFormat::SetRegisteredMediaFormat(mm
->mediaFormat
);
2146 ////////////////////////////////////////
2148 config
->DeleteGroup(H323AliasesGroup
);
2149 config
->SetPath(H323AliasesGroup
);
2150 m_manager
.h323EP
->SetLocalUserName(m_Username
);
2151 PStringList aliases
= m_manager
.h323EP
->GetAliasNames();
2152 for (size_t i
= 0; i
< m_Aliases
->GetCount(); i
++) {
2153 wxString alias
= m_Aliases
->GetString(i
);
2154 m_manager
.h323EP
->AddAliasName(alias
.c_str());
2156 key
.sprintf("%u", i
+1);
2157 config
->Write(key
, alias
);
2160 config
->SetPath(H323Group
);
2161 m_manager
.h323EP
->SetSendUserInputMode((H323Connection::SendUserInputModes
)m_DTMFSendMode
);
2162 config
->Write(DTMFSendModeKey
, m_DTMFSendMode
);
2163 SAVE_FIELD(CallIntrusionProtectionLevel
, m_manager
.h323EP
->SetCallIntrusionProtectionLevel
);
2164 SAVE_FIELD(DisableFastStart
, m_manager
.h323EP
->DisableFastStart
);
2165 SAVE_FIELD(DisableH245Tunneling
, m_manager
.h323EP
->DisableH245Tunneling
);
2166 SAVE_FIELD(DisableH245inSETUP
, m_manager
.h323EP
->DisableH245inSetup
);
2168 config
->Write(GatekeeperTTLKey
, m_GatekeeperTTL
);
2169 m_manager
.h323EP
->SetGatekeeperTimeToLive(PTimeInterval(0, m_GatekeeperTTL
));
2171 if (m_manager
.m_gatekeeperMode
!= m_GatekeeperMode
||
2172 m_manager
.m_gatekeeperAddress
!= m_GatekeeperAddress
||
2173 m_manager
.m_gatekeeperIdentifier
!= m_GatekeeperIdentifier
||
2174 m_manager
.h323EP
->GetGatekeeperUsername() != m_GatekeeperLogin
.c_str() ||
2175 m_manager
.h323EP
->GetGatekeeperPassword() != m_GatekeeperPassword
.c_str()) {
2176 SAVE_FIELD(GatekeeperMode
, m_manager
.m_gatekeeperMode
= );
2177 SAVE_FIELD(GatekeeperAddress
, m_manager
.m_gatekeeperAddress
= );
2178 SAVE_FIELD(GatekeeperIdentifier
, m_manager
.m_gatekeeperIdentifier
= );
2179 SAVE_FIELD2(GatekeeperPassword
, GatekeeperLogin
, m_manager
.h323EP
->SetGatekeeperPassword
);
2181 if (!m_manager
.StartGatekeeper())
2185 ////////////////////////////////////////
2187 config
->SetPath(SIPGroup
);
2188 SAVE_FIELD(SIPProxyUsed
, m_manager
.m_SIPProxyUsed
=);
2189 m_manager
.sipEP
->SetProxy(m_SIPProxy
, m_SIPProxyUsername
, m_SIPProxyPassword
);
2190 config
->Write(SIPProxyKey
, m_SIPProxy
);
2191 config
->Write(SIPProxyUsernameKey
, m_SIPProxyUsername
);
2192 config
->Write(SIPProxyPasswordKey
, m_SIPProxyPassword
);
2194 config
->Write(RegistrarTimeToLiveKey
, m_RegistrarTimeToLive
);
2195 m_manager
.sipEP
->SetRegistrarTimeToLive(PTimeInterval(0, m_RegistrarTimeToLive
));
2197 if (m_manager
.m_registrarUsed
!= m_RegistrarUsed
||
2198 m_manager
.m_registrarName
!= m_RegistrarName
||
2199 m_manager
.m_registrarUser
!= m_RegistrarUsername
||
2200 m_manager
.m_registrarPassword
!= m_RegistrarPassword
) {
2201 SAVE_FIELD(RegistrarUsed
, m_manager
.m_registrarUsed
=);
2202 SAVE_FIELD(RegistrarName
, m_manager
.m_registrarName
=);
2203 SAVE_FIELD(RegistrarUsername
, m_manager
.m_registrarUser
=);
2204 SAVE_FIELD(RegistrarPassword
, m_manager
.m_registrarPassword
=);
2205 m_manager
.StartRegistrar();
2208 ////////////////////////////////////////
2213 ////////////////////////////////////////
2215 config
->SetPath(TracingGroup
);
2216 int traceOptions
= 0;
2217 if (m_TraceLevelNumber
)
2218 traceOptions
|= PTrace::TraceLevel
;
2219 if (m_TraceFileLine
)
2220 traceOptions
|= PTrace::FileAndLine
;
2222 traceOptions
|= PTrace::Blocks
;
2223 if (m_TraceDateTime
)
2224 traceOptions
|= PTrace::DateAndTime
;
2225 if (m_TraceTimestamp
)
2226 traceOptions
|= PTrace::Timestamp
;
2227 if (m_TraceThreadName
)
2228 traceOptions
|= PTrace::Thread
;
2229 if (m_TraceThreadAddress
)
2230 traceOptions
|= PTrace::ThreadAddress
;
2232 config
->Write(EnableTracingKey
, m_EnableTracing
);
2233 config
->Write(TraceLevelThresholdKey
, m_TraceLevelThreshold
);
2234 config
->Write(TraceFileNameKey
, m_TraceFileName
);
2235 config
->Write(TraceOptionsKey
, traceOptions
);
2237 // Check for stopping tracing
2238 if (m_manager
.m_enableTracing
&& (!m_EnableTracing
|| m_TraceFileName
.empty()))
2239 PTrace::SetStream(NULL
);
2240 else if (m_EnableTracing
&& (!m_manager
.m_enableTracing
|| m_manager
.m_traceFileName
!= m_TraceFileName
))
2241 PTrace::Initialise(m_TraceLevelThreshold
, m_TraceFileName
, traceOptions
);
2243 PTrace::SetLevel(m_TraceLevelThreshold
);
2244 PTrace::SetOptions(traceOptions
);
2245 PTrace::ClearOptions(~traceOptions
);
2248 m_manager
.m_enableTracing
= m_EnableTracing
;
2249 m_manager
.m_traceFileName
= m_TraceFileName
;
2252 ::wxEndBusyCursor();
2258 ////////////////////////////////////////
2261 void OptionsDialog::BrowseSoundFile(wxCommandEvent
& /*event*/)
2263 wxString newFile
= wxFileSelector("Sound file to play on incoming calls",
2265 m_RingSoundFileName
,
2267 "WAV files (*.wav)|*.wav",
2268 wxOPEN
|wxFILE_MUST_EXIST
);
2269 if (!newFile
.empty()) {
2270 m_RingSoundFileName
= newFile
;
2271 TransferDataToWindow();
2276 void OptionsDialog::PlaySoundFile(wxCommandEvent
& /*event*/)
2278 PSoundChannel
speaker(m_manager
.m_RingSoundDeviceName
, PSoundChannel::Player
);
2279 speaker
.PlayFile(m_RingSoundFileName
.c_str());
2283 ////////////////////////////////////////
2284 // Networking fields
2286 void OptionsDialog::BandwidthClass(wxCommandEvent
& event
)
2288 static const char * bandwidthClasses
[] = {
2289 "14.4", "28.8", "64.0", "128", "1500", "10000"
2292 m_Bandwidth
= bandwidthClasses
[event
.GetSelection()];
2293 TransferDataToWindow();
2297 void OptionsDialog::SelectedLocalInterface(wxCommandEvent
& /*event*/)
2299 m_RemoveInterface
->Enable(m_LocalInterfaces
->GetSelection() != wxNOT_FOUND
);
2303 void OptionsDialog::ChangedInterfaceToAdd(wxCommandEvent
& /*event*/)
2305 m_AddInterface
->Enable(!m_InterfaceToAdd
->GetValue().IsEmpty());
2309 void OptionsDialog::AddInterface(wxCommandEvent
& /*event*/)
2311 m_LocalInterfaces
->Append(m_InterfaceToAdd
->GetValue());
2315 void OptionsDialog::RemoveInterface(wxCommandEvent
& /*event*/)
2317 m_InterfaceToAdd
->SetValue(m_LocalInterfaces
->GetStringSelection());
2318 m_LocalInterfaces
->Delete(m_LocalInterfaces
->GetSelection());
2319 m_RemoveInterface
->Disable();
2323 ////////////////////////////////////////
2326 void OptionsDialog::SelectedLID(wxCommandEvent
& /*event*/)
2328 bool enabled
= m_selectedLID
->GetSelection() > 0;
2329 m_selectedAEC
->Enable(enabled
);
2330 m_selectedCountry
->Enable(enabled
);
2334 ////////////////////////////////////////
2337 void OptionsDialog::AddCodec(wxCommandEvent
& /*event*/)
2339 int insertionPoint
= -1;
2340 wxArrayInt destinationSelections
;
2341 if (m_selectedCodecs
->GetSelections(destinationSelections
) > 0)
2342 insertionPoint
= destinationSelections
[0];
2344 wxArrayInt sourceSelections
;
2345 m_allCodecs
->GetSelections(sourceSelections
);
2346 for (size_t i
= 0; i
< sourceSelections
.GetCount(); i
++) {
2347 int sourceSelection
= sourceSelections
[i
];
2348 wxString value
= m_allCodecs
->GetString(sourceSelection
);
2349 void * data
= m_allCodecs
->GetClientData(sourceSelection
);
2350 value
.Remove(0, value
.Find(':')+2);
2351 if (m_selectedCodecs
->FindString(value
) < 0) {
2352 if (insertionPoint
< 0)
2353 m_selectedCodecs
->Append(value
, data
);
2355 m_selectedCodecs
->InsertItems(1, &value
, insertionPoint
);
2356 m_selectedCodecs
->SetClientData(insertionPoint
, data
);
2359 m_allCodecs
->Deselect(sourceSelections
[i
]);
2362 m_AddCodec
->Enable(false);
2366 void OptionsDialog::RemoveCodec(wxCommandEvent
& /*event*/)
2368 wxArrayInt selections
;
2369 m_selectedCodecs
->GetSelections(selections
);
2370 for (int i
= selections
.GetCount()-1; i
>= 0; i
--)
2371 m_selectedCodecs
->Delete(selections
[i
]);
2372 m_RemoveCodec
->Enable(false);
2373 m_MoveUpCodec
->Enable(false);
2374 m_MoveDownCodec
->Enable(false);
2378 void OptionsDialog::MoveUpCodec(wxCommandEvent
& /*event*/)
2380 wxArrayInt selections
;
2381 m_selectedCodecs
->GetSelections(selections
);
2382 wxString value
= m_selectedCodecs
->GetString(selections
[0]);
2383 m_selectedCodecs
->Delete(selections
[0]);
2384 m_selectedCodecs
->InsertItems(1, &value
, selections
[0]-1);
2385 m_selectedCodecs
->SetSelection(selections
[0]-1);
2386 m_MoveUpCodec
->Enable(selections
[0] > 1);
2387 m_MoveDownCodec
->Enable(true);
2391 void OptionsDialog::MoveDownCodec(wxCommandEvent
& /*event*/)
2393 wxArrayInt selections
;
2394 m_selectedCodecs
->GetSelections(selections
);
2395 wxString value
= m_selectedCodecs
->GetString(selections
[0]);
2396 m_selectedCodecs
->Delete(selections
[0]);
2397 m_selectedCodecs
->InsertItems(1, &value
, selections
[0]+1);
2398 m_selectedCodecs
->SetSelection(selections
[0]+1);
2399 m_MoveUpCodec
->Enable(true);
2400 m_MoveDownCodec
->Enable(selections
[0] < (int)m_selectedCodecs
->GetCount()-2);
2404 void OptionsDialog::SelectedCodecToAdd(wxCommandEvent
& /*event*/)
2406 wxArrayInt selections
;
2407 m_AddCodec
->Enable(m_allCodecs
->GetSelections(selections
) > 0);
2411 void OptionsDialog::SelectedCodec(wxCommandEvent
& /*event*/)
2413 wxArrayInt selections
;
2414 size_t count
= m_selectedCodecs
->GetSelections(selections
);
2415 m_RemoveCodec
->Enable(count
> 0);
2416 m_MoveUpCodec
->Enable(count
== 1 && selections
[0] > 0);
2417 m_MoveDownCodec
->Enable(count
== 1 && selections
[0] < (int)m_selectedCodecs
->GetCount()-1);
2419 m_codecOptions
->DeleteAllItems();
2420 m_codecOptionValue
->SetValue("");
2421 m_codecOptionValue
->Disable();
2424 MyMedia
* media
= (MyMedia
*)m_selectedCodecs
->GetClientData(selections
[0]);
2425 PAssert(media
!= NULL
, PLogicError
);
2426 for (PINDEX i
= 0; i
< media
->mediaFormat
.GetOptionCount(); i
++) {
2427 const OpalMediaOption
& option
= media
->mediaFormat
.GetOption(i
);
2429 item
.m_mask
= wxLIST_MASK_TEXT
|wxLIST_MASK_DATA
;
2430 item
.m_itemId
= LONG_MAX
;
2431 item
.m_text
= PwxString(option
.GetName());
2432 item
.m_data
= option
.IsReadOnly();
2433 long index
= m_codecOptions
->InsertItem(item
);
2434 m_codecOptions
->SetItem(index
, 1, PwxString(option
.AsString()));
2440 void OptionsDialog::SelectedCodecOption(wxListEvent
& /*event*/)
2443 item
.m_mask
= wxLIST_MASK_TEXT
|wxLIST_MASK_DATA
;
2444 item
.m_itemId
= m_codecOptions
->GetNextItem(-1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
2446 m_codecOptions
->GetItem(item
);
2447 m_codecOptionValue
->Enable(!item
.m_data
);
2449 m_codecOptionValue
->SetValue(item
.m_text
);
2453 void OptionsDialog::DeselectedCodecOption(wxListEvent
& /*event*/)
2455 m_codecOptionValue
->SetValue("");
2456 m_codecOptionValue
->Disable();
2460 void OptionsDialog::ChangedCodecOptionValue(wxCommandEvent
& /*event*/)
2462 PwxString newValue
= m_codecOptionValue
->GetValue();
2465 item
.m_itemId
= m_codecOptions
->GetNextItem(-1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
2466 if (item
.m_itemId
< 0)
2469 item
.m_mask
= wxLIST_MASK_TEXT
;
2471 m_codecOptions
->GetItem(item
);
2473 if (item
.m_text
== newValue
)
2476 item
.m_text
= newValue
;
2477 m_codecOptions
->SetItem(item
);
2480 m_codecOptions
->GetItem(item
);
2482 wxArrayInt selections
;
2483 PAssert(m_selectedCodecs
->GetSelections(selections
) == 1, PLogicError
);
2484 MyMedia
* media
= (MyMedia
*)m_selectedCodecs
->GetClientData(selections
[0]);
2485 PAssert(media
!= NULL
, PLogicError
);
2486 if (media
->mediaFormat
.SetOptionValue(PwxString(item
.m_text
), newValue
))
2487 media
->dirty
= true;
2489 wxMessageBox("Could not set option to specified value!", "Error", wxCANCEL
|wxICON_EXCLAMATION
);
2493 ////////////////////////////////////////
2496 void OptionsDialog::SelectedAlias(wxCommandEvent
& /*event*/)
2498 m_RemoveAlias
->Enable(m_Aliases
->GetSelection() != wxNOT_FOUND
);
2502 void OptionsDialog::ChangedNewAlias(wxCommandEvent
& /*event*/)
2505 m_AddAlias
->Enable(!m_NewAlias
->GetValue().IsEmpty());
2509 void OptionsDialog::AddAlias(wxCommandEvent
& /*event*/)
2511 m_Aliases
->Append(m_NewAlias
->GetValue());
2515 void OptionsDialog::RemoveAlias(wxCommandEvent
& /*event*/)
2517 m_NewAlias
->SetValue(m_Aliases
->GetStringSelection());
2518 m_Aliases
->Delete(m_Aliases
->GetSelection());
2519 m_RemoveAlias
->Disable();
2523 ////////////////////////////////////////
2526 void OptionsDialog::AddRoute(wxCommandEvent
& /*event*/)
2528 int pos
= m_Routes
->InsertItem(m_SelectedRoute
, m_RouteSource
->GetValue());
2529 m_Routes
->SetItem(pos
, 1, m_RoutePattern
->GetValue());
2530 m_Routes
->SetItem(pos
, 2, m_RouteDestination
->GetValue());
2534 void OptionsDialog::RemoveRoute(wxCommandEvent
& /*event*/)
2536 m_Routes
->DeleteItem(m_SelectedRoute
);
2540 void OptionsDialog::SelectedRoute(wxListEvent
& event
)
2542 m_SelectedRoute
= event
.GetIndex();
2543 m_RemoveRoute
->Enable(true);
2547 void OptionsDialog::DeselectedRoute(wxListEvent
& /*event*/)
2549 m_SelectedRoute
= INT_MAX
;
2550 m_RemoveRoute
->Enable(false);
2554 void OptionsDialog::ChangedRouteInfo(wxCommandEvent
& /*event*/)
2556 m_AddRoute
->Enable(!m_RoutePattern
->GetValue().IsEmpty() && !m_RouteDestination
->GetValue().IsEmpty());
2560 ///////////////////////////////////////////////////////////////////////////////
2562 BEGIN_EVENT_TABLE(CallDialog
, wxDialog
)
2563 EVT_BUTTON(XRCID("wxID_OK"), CallDialog::OnOK
)
2564 EVT_TEXT(XRCID("Address"), CallDialog::OnAddressChange
)
2567 CallDialog::CallDialog(wxFrame
* parent
)
2569 wxXmlResource::Get()->LoadDialog(this, parent
, "CallDialog");
2571 m_ok
= FindWindowByNameAs
<wxButton
>(this, "wxID_OK");
2574 m_AddressCtrl
= FindWindowByNameAs
<wxComboBox
>(this, "Address");
2575 m_AddressCtrl
->SetValidator(wxGenericValidator(&m_Address
));
2577 wxConfigBase
* config
= wxConfig::Get();
2578 config
->SetPath(RecentCallsGroup
);
2581 if (config
->GetFirstEntry(entryName
, entryIndex
)) {
2584 if (config
->Read(entryName
, &address
))
2585 m_AddressCtrl
->AppendString(address
);
2586 } while (config
->GetNextEntry(entryName
, entryIndex
));
2591 void CallDialog::OnOK(wxCommandEvent
& event
)
2593 bool addNewEntry
= true;
2595 wxConfigBase
* config
= wxConfig::Get();
2596 config
->DeleteGroup(RecentCallsGroup
);
2597 config
->SetPath(RecentCallsGroup
);
2600 for (index
= 0; index
< m_AddressCtrl
->GetCount(); ++index
) {
2601 wxString entry
= m_AddressCtrl
->GetString(index
);
2604 key
.sprintf("%u", index
+1);
2605 config
->Write(key
, entry
);
2607 if (m_Address
== entry
)
2608 addNewEntry
= false;
2610 if (index
>= MaxSavedRecentCalls
-(addNewEntry
?1:0))
2616 key
.sprintf("%u", index
+1);
2617 config
->Write(key
, m_Address
);
2622 void CallDialog::OnAddressChange(wxCommandEvent
& WXUNUSED(event
))
2624 TransferDataFromWindow();
2625 m_ok
->Enable(!m_Address
.IsEmpty());
2629 ///////////////////////////////////////////////////////////////////////////////
2631 BEGIN_EVENT_TABLE(AnswerPanel
, wxPanel
)
2632 EVT_BUTTON(XRCID("AnswerCall"), AnswerPanel::OnAnswer
)
2633 EVT_BUTTON(XRCID("RejectCall"), AnswerPanel::OnReject
)
2636 AnswerPanel::AnswerPanel(MyManager
& manager
, wxWindow
* parent
)
2637 : m_manager(manager
)
2639 wxXmlResource::Get()->LoadPanel(this, parent
, "AnswerPanel");
2643 void AnswerPanel::OnAnswer(wxCommandEvent
& /*event*/)
2645 m_manager
.AnswerCall();
2649 void AnswerPanel::OnReject(wxCommandEvent
& /*event*/)
2651 m_manager
.RejectCall();
2655 ///////////////////////////////////////////////////////////////////////////////
2657 BEGIN_EVENT_TABLE(CallingPanel
, wxPanel
)
2658 EVT_BUTTON(XRCID("HangUpCall"), CallingPanel::OnHangUp
)
2661 CallingPanel::CallingPanel(MyManager
& manager
, wxWindow
* parent
)
2662 : m_manager(manager
)
2664 wxXmlResource::Get()->LoadPanel(this, parent
, "CallingPanel");
2668 void CallingPanel::OnHangUp(wxCommandEvent
& /*event*/)
2670 m_manager
.HangUpCall();
2674 ///////////////////////////////////////////////////////////////////////////////
2676 const int VU_UPDATE_TIMER_ID
= 1000;
2678 BEGIN_EVENT_TABLE(InCallPanel
, wxPanel
)
2679 EVT_BUTTON(XRCID("HangUp"), InCallPanel::OnHangUp
)
2680 EVT_BUTTON(XRCID("Input1"), InCallPanel::OnUserInput1
)
2681 EVT_BUTTON(XRCID("Input2"), InCallPanel::OnUserInput2
)
2682 EVT_BUTTON(XRCID("Input3"), InCallPanel::OnUserInput3
)
2683 EVT_BUTTON(XRCID("Input4"), InCallPanel::OnUserInput4
)
2684 EVT_BUTTON(XRCID("Input5"), InCallPanel::OnUserInput5
)
2685 EVT_BUTTON(XRCID("Input6"), InCallPanel::OnUserInput6
)
2686 EVT_BUTTON(XRCID("Input7"), InCallPanel::OnUserInput7
)
2687 EVT_BUTTON(XRCID("Input8"), InCallPanel::OnUserInput8
)
2688 EVT_BUTTON(XRCID("Input9"), InCallPanel::OnUserInput9
)
2689 EVT_BUTTON(XRCID("Input0"), InCallPanel::OnUserInput0
)
2690 EVT_BUTTON(XRCID("InputStar"), InCallPanel::OnUserInputStar
)
2691 EVT_BUTTON(XRCID("InputHash"), InCallPanel::OnUserInputHash
)
2692 EVT_BUTTON(XRCID("InputFlash"), InCallPanel::OnUserInputFlash
)
2694 EVT_COMMAND_SCROLL(XRCID("SpeakerVolume"), InCallPanel::SpeakerVolume
)
2695 EVT_COMMAND_SCROLL(XRCID("MicrophoneVolume"), InCallPanel::MicrophoneVolume
)
2697 EVT_TIMER(VU_UPDATE_TIMER_ID
, InCallPanel::OnUpdateVU
)
2700 InCallPanel::InCallPanel(MyManager
& manager
, wxWindow
* parent
)
2701 : m_manager(manager
)
2702 , m_vuTimer(this, VU_UPDATE_TIMER_ID
)
2704 wxXmlResource::Get()->LoadPanel(this, parent
, "InCallPanel");
2706 m_SpeakerVolume
= FindWindowByNameAs
<wxSlider
>(this, "SpeakerVolume");
2707 m_MicrophoneVolume
= FindWindowByNameAs
<wxSlider
>(this, "MicrophoneVolume");
2708 m_vuSpeaker
= FindWindowByNameAs
<wxGauge
>(this, "SpeakerGauge");
2709 m_vuMicrophone
= FindWindowByNameAs
<wxGauge
>(this, "MicrophoneGauge");
2715 bool InCallPanel::Show(bool show
)
2717 wxConfigBase
* config
= wxConfig::Get();
2718 config
->SetPath(AudioGroup
);
2720 if (show
|| m_FirstTime
) {
2721 m_FirstTime
= false;
2724 config
->Read(SpeakerVolumeKey
, &value
);
2725 m_SpeakerVolume
->SetValue(value
);
2726 SetVolume(false, value
);
2729 config
->Read(MicrophoneVolumeKey
, &value
);
2730 m_MicrophoneVolume
->SetValue(value
);
2731 SetVolume(true, value
);
2734 m_vuTimer
.Start(250);
2737 config
->Write(SpeakerVolumeKey
, m_SpeakerVolume
->GetValue());
2738 config
->Write(MicrophoneVolumeKey
, m_MicrophoneVolume
->GetValue());
2743 return wxPanel::Show(show
);
2747 void InCallPanel::OnHangUp(wxCommandEvent
& /*event*/)
2749 m_manager
.HangUpCall();
2752 #define ON_USER_INPUT_HANDLER(i,c) \
2753 void InCallPanel::OnUserInput##i(wxCommandEvent &) \
2754 { m_manager.SendUserInput(c); }
2756 ON_USER_INPUT_HANDLER(1,'1')
2757 ON_USER_INPUT_HANDLER(2,'2')
2758 ON_USER_INPUT_HANDLER(3,'3')
2759 ON_USER_INPUT_HANDLER(4,'4')
2760 ON_USER_INPUT_HANDLER(5,'5')
2761 ON_USER_INPUT_HANDLER(6,'6')
2762 ON_USER_INPUT_HANDLER(7,'7')
2763 ON_USER_INPUT_HANDLER(8,'8')
2764 ON_USER_INPUT_HANDLER(9,'9')
2765 ON_USER_INPUT_HANDLER(0,'0')
2766 ON_USER_INPUT_HANDLER(Star
,'*')
2767 ON_USER_INPUT_HANDLER(Hash
,'#')
2768 ON_USER_INPUT_HANDLER(Flash
,'!')
2771 void InCallPanel::SpeakerVolume(wxScrollEvent
& event
)
2773 SetVolume(false, event
.GetPosition());
2777 void InCallPanel::MicrophoneVolume(wxScrollEvent
& event
)
2779 SetVolume(true, event
.GetPosition());
2783 void InCallPanel::SetVolume(bool isMicrophone
, int value
)
2785 PSafePtr
<OpalConnection
> connection
= m_manager
.GetUserConnection();
2786 if (connection
!= NULL
)
2787 connection
->SetAudioVolume(isMicrophone
, value
);
2791 static void SetGauge(wxGauge
* gauge
, int level
)
2793 if (level
< 0 || level
> 32767) {
2798 gauge
->SetValue((int)(log10(9.0*level
/32768.0+1)*100)); // Convert to logarithmic scale
2802 void InCallPanel::OnUpdateVU(wxTimerEvent
& event
)
2806 PSafePtr
<OpalConnection
> connection
= m_manager
.GetUserConnection();
2807 if (connection
!= NULL
) {
2808 spkLevel
= connection
->GetAudioSignalLevel(false);
2809 micLevel
= connection
->GetAudioSignalLevel(true);
2812 SetGauge(m_vuSpeaker
, spkLevel
);
2813 SetGauge(m_vuMicrophone
, micLevel
);
2817 ///////////////////////////////////////////////////////////////////////////////
2819 BEGIN_EVENT_TABLE(SpeedDialDialog
, wxDialog
)
2820 EVT_TEXT(XRCID("SpeedDialName"), SpeedDialDialog::OnChange
)
2821 EVT_TEXT(XRCID("SpeedDialNumber"), SpeedDialDialog::OnChange
)
2824 SpeedDialDialog::SpeedDialDialog(MyManager
* manager
)
2825 : m_manager(*manager
)
2827 wxXmlResource::Get()->LoadDialog(this, manager
, "SpeedDialDialog");
2829 m_ok
= FindWindowByNameAs
<wxButton
>(this, "wxID_OK");
2831 m_nameCtrl
= FindWindowByNameAs
<wxTextCtrl
>(this, "SpeedDialName");
2832 m_nameCtrl
->SetValidator(wxGenericValidator(&m_Name
));
2834 m_numberCtrl
= FindWindowByNameAs
<wxTextCtrl
>(this, "SpeedDialNumber");
2835 m_numberCtrl
->SetValidator(wxGenericValidator(&m_Number
));
2837 FindWindowByName("SpeedDialAddress")->SetValidator(wxGenericValidator(&m_Address
));
2838 FindWindowByName("SpeedDialDescription")->SetValidator(wxGenericValidator(&m_Description
));
2840 m_inUse
= FindWindowByNameAs
<wxStaticText
>(this, "SpeedDialInUse");
2841 m_ambiguous
= FindWindowByNameAs
<wxStaticText
>(this, "SpeedDialAmbiguous");
2845 void SpeedDialDialog::OnChange(wxCommandEvent
& WXUNUSED(event
))
2847 wxString newName
= m_nameCtrl
->GetValue();
2848 bool inUse
= newName
!= m_Name
&& m_manager
.HasSpeedDialName(newName
);
2849 m_inUse
->Show(inUse
);
2851 m_ok
->Enable(!newName
.IsEmpty() && !inUse
);
2853 m_ambiguous
->Show(m_manager
.GetSpeedDialIndex(m_numberCtrl
->GetValue(), m_Number
) >= 0);
2857 ///////////////////////////////////////////////////////////////////////////////
2859 MyPCSSEndPoint::MyPCSSEndPoint(MyManager
& manager
)
2860 : OpalPCSSEndPoint(manager
),
2866 BOOL
MyPCSSEndPoint::OnShowIncoming(const OpalPCSSConnection
& connection
)
2868 m_manager
.OnRinging(connection
);
2874 BOOL
MyPCSSEndPoint::OnShowOutgoing(const OpalPCSSConnection
& connection
)
2877 LogWindow
<< connection
.GetRemotePartyName() << " is ringing on "
2878 << now
.AsString("w h:mma") << " ..." << endl
;
2883 ///////////////////////////////////////////////////////////////////////////////
2886 MyH323EndPoint::MyH323EndPoint(MyManager
& manager
)
2887 : H323EndPoint(manager
),
2893 void MyH323EndPoint::OnRegistrationConfirm()
2895 // LogWindow << "H.323 registration successful." << endl;
2901 ///////////////////////////////////////////////////////////////////////////////
2904 MySIPEndPoint::MySIPEndPoint(MyManager
& manager
)
2905 : SIPEndPoint(manager
),
2911 void MySIPEndPoint::OnRegistered()
2913 LogWindow
<< "SIP registration successful." << endl
;
2919 // End of File ///////////////////////////////////////////////////////////////