main.cxx
上传用户:sdyzjx
上传日期:2007-01-06
资源大小:47k
文件大小:86k
- /*
- * main.cxx
- *
- * PWLib application source file for OpenPhone
- *
- * Open H323 Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Open H323 Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions of this code were written with the assisance of funding from
- * Vovida Networks, Inc. http://www.vovida.com.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): Portions Copyright 1999 NEWLINK
- *
- * $Log: main.cxx,v $
- * Revision 1.87 2000/07/15 09:48:49 robertj
- * Added message for unregistering from gatekeeper.
- *
- * Revision 1.86 2000/07/13 15:49:52 robertj
- * Renamed all codecs so obvious whether software or hardware.
- * Split autoStartVideo so can select receive and transmit independently
- * Fixed the previous fix in the most recent calls list.
- * Added frame count to message on audio channel open.
- *
- * Revision 1.85 2000/07/11 19:54:47 robertj
- * Fixed crash if closed speed dial window while handset off hook.
- * Fixed recent call list so saves recent calls now.
- * Added ability to set the frames per packet in audio codecs.
- * Added correct insertion of H.261 capabilities for on the fly qcif/cif switching.
- *
- * Revision 1.84 2000/07/09 14:51:17 robertj
- * Fixed incorrect colours in video display window.
- *
- * Revision 1.83 2000/07/02 09:14:09 robertj
- * Fixed problems with closing video receive window under Win32.
- *
- * Revision 1.82 2000/06/29 11:00:04 robertj
- * Added user interface for sound buffer depth adjustment.
- *
- * Revision 1.81 2000/06/29 06:20:53 robertj
- * Fixed deadlock when exiting application while in a call.
- *
- * Revision 1.80 2000/06/20 12:51:23 robertj
- * Changed IXJ driver open so does not change selected line to PSTN.
- *
- * Revision 1.79 2000/06/20 03:18:05 robertj
- * Added function to get name of gatekeeper, subtle difference from getting identifier.
- *
- * Revision 1.78 2000/06/20 02:38:28 robertj
- * Changed H323TransportAddress to default to IP.
- *
- * Revision 1.77 2000/06/19 00:32:22 robertj
- * Changed functionf or adding all lid capabilities to not assume it is to an endpoint.
- *
- * Revision 1.76 2000/06/15 01:46:15 robertj
- * Added channel pause (aka mute) functions.
- *
- * Revision 1.75 2000/06/09 07:50:11 robertj
- * Changed PSTN line psuedo gateway to use LID Dial function.
- *
- * Revision 1.74 2000/06/07 05:48:06 robertj
- * Added call forwarding.
- *
- * Revision 1.73 2000/06/05 04:45:12 robertj
- * Added LPC-10 2400bps codec
- *
- * Revision 1.72 2000/05/30 10:19:28 robertj
- * Added function to add capabilities given a LID.
- * Improved LID capabilities so cannot create one that is not explicitly supported.
- *
- * Revision 1.71 2000/05/23 12:57:37 robertj
- * Added ability to change IP Type Of Service code from applications.
- *
- * Revision 1.70 2000/05/23 11:32:37 robertj
- * Rewrite of capability table to combine 2 structures into one and move functionality into that class
- * allowing some normalisation of usage across several applications.
- * Changed H323Connection so gets a copy of capabilities instead of using endponts, allows adjustments
- * to be done depending on the remote client application.
- *
- * Revision 1.69 2000/05/16 08:23:34 robertj
- * Added ability to change silence detect mode on active call.
- *
- * Revision 1.68 2000/05/10 05:16:00 robertj
- * Added hook flash to user indications. Also allowed selection of the User Indication
- * method to be used in the H.245 protocol.
- *
- * Revision 1.67 2000/05/10 04:06:19 robertj
- * Added ability to disable an audio codec as well as change its priority.
- *
- * Revision 1.66 2000/05/05 03:45:05 robertj
- * Added ability to set multiple aliases for endpoint.
- * Added "bandwidth by type" so can specify by saying "T1" for example.
- *
- * Revision 1.65 2000/05/04 11:53:38 robertj
- * Added Packets Too Late statistics.
- * Fixed gatekeeper detection so if "required", disables call menus.
- *
- * Revision 1.64 2000/05/01 13:00:29 robertj
- * Changed SetCapability() to append capabilities to TCS, helps with assuring no gaps in set.
- *
- * Revision 1.63 2000/05/01 08:20:28 robertj
- * Fixed capability loading so do not need to restart program when altering video parameters.
- *
- * Revision 1.62 2000/04/19 02:07:29 robertj
- * Fixed problems with video window.
- *
- * Revision 1.61 2000/04/14 21:48:49 robertj
- * Fixed gatekeeper search default value to OFF.
- *
- * Revision 1.60 2000/04/13 00:14:25 robertj
- * Fixed display of correct ixj card in drop down box on first time use.
- * Changed default gatekeeper detection to OFF.
- *
- * Revision 1.59 2000/04/11 03:59:33 robertj
- * Added new call end reasons for gatekeeper denied calls.
- *
- * Revision 1.58 2000/04/06 19:59:56 robertj
- * Used named constants instead of literals for xJack line selection.
- *
- * Revision 1.57 2000/04/06 17:38:52 robertj
- * Fixed ability to change Quicknet card without restarting program.
- *
- * Revision 1.56 2000/04/05 20:56:47 robertj
- * Added more statistics.
- *
- * Revision 1.55 2000/04/04 20:37:10 robertj
- * Fixed inability to set discovery mode in dialog, thanks Thien Nguyen.
- *
- * Revision 1.54 2000/03/30 19:57:58 robertj
- * Fixed some call end message strings, also added cap exchange failure message.
- * Added G.728/G.729 support via new LID GetPayloadTypes() function.
- * Fixed possible deadlock exiting application with active call (Win32 only).
- *
- * Revision 1.53 2000/03/21 03:06:48 robertj
- * Changes to make RTP TX of exact numbers of frames in some codecs.
- *
- * Revision 1.52 2000/03/20 20:30:09 robertj
- * Usability improvement, hide speed dial dialog so can see dial progress.
- *
- * Revision 1.51 2000/03/04 13:44:00 robertj
- * Added timer to ring every 5 seconds and not just once!
- *
- * Revision 1.50 2000/03/04 12:16:55 robertj
- * Added ring sound file to standard sound device on incoming calls.
- *
- * Revision 1.49 2000/02/29 12:58:27 robertj
- * Added extra tracing options to dialog.
- *
- * Revision 1.48 2000/02/17 12:25:16 robertj
- * Added user indication send/receive and option to disable H.245 tunneling.
- *
- * Revision 1.47 2000/02/16 05:21:39 robertj
- * Added dialog parametes for vide transmission, still no grabber yet.
- *
- * Revision 1.46 2000/02/16 03:32:47 robertj
- * Fixed bug where selecting previous address in make call dialog, didn't use gateway.
- *
- * Revision 1.45 2000/01/20 07:55:12 robertj
- * Fixed shutdown bug locking up if Quicknet card used.
- *
- * Revision 1.44 2000/01/07 08:28:09 robertj
- * Additions and changes to line interface device base class.
- *
- * Revision 1.43 1999/12/31 00:05:06 robertj
- * Added Microsoft ACM G.723.1 Codec capability.
- *
- * Revision 1.42 1999/12/23 23:02:35 robertj
- * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
- *
- * Revision 1.41 1999/11/29 04:50:11 robertj
- * Added adaptive threshold calculation to silence detection.
- *
- * Revision 1.40 1999/11/23 11:09:43 robertj
- * Fixed speakerphone state reset and uninitialised speakerphone flag variable.
- *
- * Revision 1.39 1999/11/22 13:32:19 robertj
- * Added more calling tones.
- *
- * Revision 1.38 1999/11/22 11:20:47 robertj
- * Fixed problem with handset pick up while making H.323 call but before connected.
- *
- * Revision 1.37 1999/11/22 10:07:23 robertj
- * Fixed some errors in correct termination states.
- *
- * Revision 1.36 1999/11/22 00:56:34 robertj
- * Improved reason display for connection failure.
- *
- * Revision 1.35 1999/11/20 00:30:02 robertj
- * Fixed incorrect call mode when replacing up handset after outside line call.
- *
- * Revision 1.34 1999/11/19 13:00:52 robertj
- * Added HangingUp state so can't start new call till old one fully cleared.
- *
- * Revision 1.33 1999/11/19 09:41:54 robertj
- * Fixed decimals on call duration string.
- *
- * Revision 1.32 1999/11/19 09:16:04 robertj
- * Added some times for call start and duration, reduced default jitter and removed G729/729.
- *
- * Revision 1.31 1999/11/18 12:50:49 robertj
- * Fixed ring cadence value.
- *
- * Revision 1.30 1999/11/17 03:49:51 robertj
- * Added RTP statistics display.
- *
- * Revision 1.29 1999/11/16 13:22:24 robertj
- * Improved versioning in about dialog (version number now in single place)
- *
- * Revision 1.28 1999/11/16 11:32:06 robertj
- * Added some calling tones.
- *
- * Revision 1.27 1999/11/13 14:13:08 robertj
- * Changes to make silence detection selectable, disable quicknet option if no cards and fixed some UI errors.
- *
- * Revision 1.26 1999/11/11 23:35:45 robertj
- * Fixed GCC warnings
- *
- * Revision 1.25 1999/11/11 23:14:40 robertj
- * Fixed turning off ring on answering call and disabling call menu if initialisation failed.
- *
- * Revision 1.24 1999/11/11 08:54:27 robertj
- * Changed preferred codec function to be full codec ordering.
- *
- * Revision 1.23 1999/11/11 01:20:48 robertj
- * Numerous enhancements to get nearly feature complete for version 1.
- *
- * Revision 1.22 1999/11/06 03:48:36 robertj
- * Added shells for mute functions
- *
- * Revision 1.21 1999/11/05 10:51:17 robertj
- * Fixed problem with new ixj channel doing incorrect double initialise
- *
- * Revision 1.20 1999/11/05 08:54:41 robertj
- * Rewrite of ixj interface code to fix support for arbitrary codecs.
- *
- * Revision 1.19 1999/11/01 00:50:16 robertj
- * Added receive H.261 video window
- *
- * Revision 1.18 1999/10/30 13:44:03 robertj
- * Fixed duplicate ID in resource strings.
- *
- * Revision 1.17 1999/10/30 12:45:47 robertj
- * Added stop channel message, outside line message and G728/G729 interlock for LineJACK
- *
- * Revision 1.16 1999/10/29 12:09:14 robertj
- * Fixed compiling no trace version.
- *
- * Revision 1.15 1999/10/29 02:28:24 robertj
- * Fixed unix compatibility problem.
- *
- * Revision 1.14 1999/10/29 02:26:52 robertj
- * Added scrollable status window and better termination information.
- *
- * Revision 1.13 1999/10/28 12:21:34 robertj
- * Added AEC support and speakerphone switching button.
- *
- * Revision 1.12 1999/10/27 06:32:50 robertj
- * Changes to prevent H225 alerting message being sent if "engaged".
- *
- * Revision 1.11 1999/10/24 15:29:53 robertj
- * Fixed warning on NoTrace build
- *
- * Revision 1.10 1999/10/24 14:44:00 robertj
- * Removed EnableDetectDTMF() as unix ioctl does not exist.
- *
- * Revision 1.9 1999/10/24 14:20:11 robertj
- * Fixed GCC compatibility
- *
- * Revision 1.8 1999/10/24 12:59:40 robertj
- * Added platform independent support for Quicknet xJACK cards.
- *
- * Revision 1.7 1999/10/09 04:19:30 robertj
- * Fixed error passing PString as ... parameter, needs (const char *) cast
- *
- * Revision 1.6 1999/10/08 00:28:21 robertj
- * Fixed some bugs in trace dialog
- *
- * Revision 1.5 1999/10/07 07:37:31 robertj
- * Added auto-answer and trace options (thanks David Iodice of NEWLINK)
- *
- * Revision 1.4 1999/09/25 00:25:39 robertj
- * Used new, neater, capability addition code.
- *
- * Revision 1.3 1999/09/09 01:09:46 robertj
- * Added support for video capabilities & codec, still needs the actual codec itself!
- *
- * Revision 1.2 1999/09/01 06:12:21 robertj
- * Added gatekeeper support.
- *
- * Revision 1.1 1999/08/25 05:16:11 robertj
- * GUI test application.
- *
- * Revision 1.2 1999/01/26 06:35:07 robertj
- * Fixed $LOG$ variable in template files
- *
- */
- #include <pwlib.h>
- #include "main.h"
- #include "version.h"
- #if PTRACING
- #include "resources.h"
- #else
- #include "resources_notrace.h"
- #endif
- #include "gsmcodec.h"
- #include "lpc10codec.h"
- #include "h261codec.h"
- #ifdef WIN32
- #include "acmcodec.h"
- #endif
- #define ENABLE_TRANSMITTER 1 // Clear to temporarily disable the transmitter start up
- #define ENABLE_RECEIVER 1 // Clear to temporarily disable the receiver acceptance
- PCREATE_PROCESS(OpenPhone);
- const char CodecsConfigSection[] = "Codecs";
- const char RecentCallsConfigSection[] = "Recent Calls";
- const char SpeedDialConfigSection[] = "Speed Dial";
- const char MainWindowTopConfigKey[] = "MainWindowTop";
- const char MainWindowLeftConfigKey[] = "MainWindowLeft";
- const char MainWindowWidthConfigKey[] = "MainWindowWidth";
- const char MainWindowHeightConfigKey[] = "MainWindowHeight";
- const char LocalVideoWindowTopConfigKey[] = "LocalVideoWindowTop";
- const char LocalVideoWindowLeftConfigKey[] = "LocalVideoWindowLeft";
- const char RemoteVideoWindowTopConfigKey[] = "RemoteVideoWindowTop";
- const char RemoteVideoWindowLeftConfigKey[] = "RemoteVideoWindowLeft";
- const char AutoAnswerConfigKey[] = "AutoAnswer";
- const char DtmfAsStringConfigKey[] = "DtmfAsString";
- const char SilenceDetectConfigKey[] = "SilenceDetect";
- const char NoFastStartConfigKey[] = "NoFastStart";
- const char NoTunnelingConfigKey[] = "NoTunneling";
- const char MaxRecentCallsConfigKey[] = "MaxRecentCalls";
- const char IpTosConfigKey[] = "IpTOS";
- const char UsernameConfigKey[] = "Username";
- const char AliasConfigKey[] = "Alias %u";
- const char AlwaysForwardPartyConfigKey[] = "AlwaysForwardParty";
- const char BusyForwardPartyConfigKey[] = "BusyForwardParty";
- const char NoAnswerForwardPartyConfigKey[] = "NoAnswerForwardParty";
- const char NoAnswerTimeConfigKey[] = "NoAnswerTime";
- const char RingSoundFileConfigKey[] = "RingSoundFile";
- const char SoundBuffersConfigKey[] = "SoundBuffers";
- const char AECConfigKey[] = "AEC";
- const char JitterConfigKey[] = "Jitter";
- const char BandwidthTypeConfigKey[] = "BandwidthType";
- const char BandwidthConfigKey[] = "Bandwidth";
- const char UseGatekeeperConfigKey[] = "UseGatekeeper";
- const char RequireGatekeeperConfigKey[] = "RequireGatekeeper";
- const char GatekeeperHostConfigKey[] = "GatekeeperHost";
- const char SoundPlayConfigKey[] = "SoundPlayDevice";
- const char SoundRecordConfigKey[] = "SoundRecordDevice";
- const char SpeakerVolumeConfigKey[] = "SpeakerVolume";
- const char MicrophoneVolumeConfigKey[] = "MicrophoneVolume";
- const char UseQuicknetConfigKey[] = "UseQuicknet";
- const char QuicknetDeviceConfigKey[] = "QuicknetDevice";
- const char H261QCIFConfigKey[] = "H261_QCIF";
- const char H261CIFConfigKey[] = "H261_CIF";
- const char AutoReceiveVideoConfigKey[] = "AutoReceiveVideo";
- const char VideoSizeConfigKey[] = "VideoSize";
- const char VideoSourceConfigKey[] = "VideoSource";
- const char VideoFormatConfigKey[] = "VideoFormat";
- const char VideoQualityConfigKey[] = "VideoQuality";
- #if PTRACING
- const char TraceFileConfigKey[] = "TraceFile";
- const char TraceLevelConfigKey[] = "TraceLevel";
- const char TraceBlockConfigKey[] = "TraceBlocks";
- const char TraceDateTimeConfigKey[] = "TraceDateAndTime";
- const char TraceTimestampConfigKey[] = "TraceTimestamp";
- const char TraceThreadsConfigKey[] = "TraceThreads";
- const char TraceThreadAddresssConfigKey[] = "TraceThreadAddresss";
- const char TraceLevelDisplayConfigKey[] = "TraceLevelDisplay";
- const char TraceFileLineConfigKey[] = "TraceFileAndLine";
- #endif
- const char InternalGatewayName[] = "<<Local-PSTN>>";
- const char CodecsConfigKey[] = "Codec%u";
- const char OnCodecSuffix[] = " (On)";
- const char OffCodecSuffix[] = " (Off)";
- const DWORD RingCadence = 0x145; // 0001 0100 0101
- const PDIMENSION StatusWindowHeight = 25;
- const PDIMENSION CallButtonHeight = 15;
- const PDIMENSION ScrollBarHeight = 12;
- const PDIMENSION SpeedDialButtonHeight = 12;
- #define new PNEW
- ///////////////////////////////////////////////////////////////////////////////
- OpenPhone::OpenPhone()
- : PApplication("Equivalence", "OpenPhone",
- MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
- {
- }
- void OpenPhone::Main()
- {
- // create the main window and endpoint
- new MainWindow(GetArguments());
- // enter the main loop
- PApplication::Main();
- }
- void OpenPhone::OnAbout()
- {
- AboutDialog dlg(mainWindow);
- dlg.version->SetName(dlg.version->GetName() + GetVersion(TRUE));
- dlg.RunModal();
- }
- ///////////////////////////////////////////////////////////////////////////////
- MainWindow::MainWindow(PArgList & /*args*/)
- #ifdef _MSC_VER
- #pragma warning(disable:4355)
- #endif
- : endpoint(this)
- #ifdef _MSC_VER
- #pragma warning(default:4355)
- #endif
- {
- PConfig config;
- #if PTRACING
- myTraceFile = NULL;
- OpenTraceFile(config);
- #endif
- SetTitle(PResourceString(IDS_TITLE));
- SetIcon(PIcon(IDI_MAIN_WINDOW));
- myMainMenu = new MainMenu(this);
- SetMenu(myMainMenu);
- // set the background colour and load the image
- SetBackgroundColour(PColour::Grey);
- // set the minimum window size
- SetMinSize(150, 50, LocalCoords);
- // Set remembered position of main window
- PPoint pos(config.GetInteger(MainWindowLeftConfigKey, INT_MAX),
- config.GetInteger(MainWindowTopConfigKey, INT_MAX));
- if (pos != PPoint(INT_MAX, INT_MAX))
- SetPosition(pos, TopLeftPixels, TopLeftPixels);
- PDim dim(config.GetInteger(MainWindowWidthConfigKey, 0),
- config.GetInteger(MainWindowHeightConfigKey, 0));
- if (dim != PDim(0, 0))
- SetDimensions(dim, PixelCoords);
- else
- SetDimensions(160, StatusWindowHeight +
- CallButtonHeight +
- ScrollBarHeight +
- SpeedDialButtonHeight,
- LocalCoords);
- dim = GetDimensions(LocalCoords);
- // create status window
- statusWindow = new PStringListBox(this, PListBox::NotSorted);
- statusWindow->SetDimensions(dim.Width(), StatusWindowHeight, LocalCoords);
- statusWindow->SetPosition(0, 0);
- statusWindow->SetBackgroundColour(PColour::Black);
- statusWindow->SetForegroundColour(PColour::Green);
- statusWindow->Show();
- answerButton = new PTextButton(this, PResourceString(IDS_ANSWERCALL), PCREATE_NOTIFIER(OnAnswerButton));
- answerButton->SetDimensions(dim.Width()/2, CallButtonHeight, LocalCoords);
- answerButton->SetPosition(0, StatusWindowHeight);
- refuseButton = new PTextButton(this, PResourceString(IDS_REFUSECALL), PCREATE_NOTIFIER(OnRefuseButton));
- refuseButton->SetDimensions(dim.Width()/2, CallButtonHeight, LocalCoords);
- refuseButton->SetPosition(dim.Width()/2, StatusWindowHeight);
- hangUpButton = new PTextButton(this, PResourceString(IDS_HANGUP), PCREATE_NOTIFIER(OnHangUpButton));
- hangUpButton->SetDimensions(dim.Width()/2, CallButtonHeight, LocalCoords);
- hangUpButton->SetPosition(0, StatusWindowHeight);
- speakerButton = new PTextButton(this, PResourceString(IDS_SPEAKERPHONE), PCREATE_NOTIFIER(OnSpeakerButton));
- speakerButton->SetDimensions(dim.Width()/2, CallButtonHeight, LocalCoords);
- speakerButton->SetPosition(dim.Width()/2, StatusWindowHeight);
- makeCallButton = new PTextButton(this, PResourceString(IDS_MAKECALL), PCREATE_NOTIFIER(OnCallButton));
- makeCallButton->SetDimensions(dim.Width(), CallButtonHeight, LocalCoords);
- makeCallButton->SetPosition(0, StatusWindowHeight);
- speakerEnable = new PCheckBox(this, PResourceString(IDS_SPEAKER), PCREATE_NOTIFIER(OnSpeakerEnable));
- speakerEnable->SetValue(TRUE);
- PDim boxSize = speakerEnable->GetDimensions(LocalCoords);
- boxSize.AddWidth(4);
- speakerEnable->SetDimensions(boxSize, LocalCoords);
- PSCROLLBAR_VALUE spkrVolume = (PSCROLLBAR_VALUE)config.GetInteger(SpeakerVolumeConfigKey, 128);
- speakerVolume = new PHorizontalScrollBar(this, PCREATE_NOTIFIER(OnSpeakerVolume),
- 255, 0, spkrVolume, 5, 25);
- PDIMENSION scrollBarWidth = dim.Width()/2 - boxSize.Width();
- speakerVolume->SetDimensions(scrollBarWidth, ScrollBarHeight, LocalCoords);
- speakerVolume->SetPosition(0, StatusWindowHeight+CallButtonHeight);
- speakerEnable->SetPosition(scrollBarWidth, StatusWindowHeight+CallButtonHeight+(ScrollBarHeight-boxSize.Height())/2);
- microphoneEnable = new PCheckBox(this, PResourceString(IDS_MICROPHONE), PCREATE_NOTIFIER(OnMicrophoneEnable));
- microphoneEnable->SetValue(TRUE);
- boxSize = microphoneEnable->GetDimensions(LocalCoords);
- boxSize.AddWidth(4);
- microphoneEnable->SetDimensions(boxSize, LocalCoords);
- microphoneEnable->SetPosition(dim.Width()/2-boxSize.Width(), StatusWindowHeight+CallButtonHeight+(ScrollBarHeight-boxSize.Height())/2);
- PSCROLLBAR_VALUE mikeVolume = (PSCROLLBAR_VALUE)config.GetInteger(MicrophoneVolumeConfigKey, 128);
- microphoneVolume = new PHorizontalScrollBar(this, PCREATE_NOTIFIER(OnMicrophoneVolume),
- 255, 0, mikeVolume, 5, 25);
- microphoneVolume->SetDimensions(dim.Width()/2-boxSize.Width(), ScrollBarHeight, LocalCoords);
- microphoneVolume->SetPosition(dim.Width()/2, StatusWindowHeight+CallButtonHeight);
- AddSpeedDialButtons();
- statisticsDialog = new StatisticsDlg(this);
- statisticsDialog->Hide();
- //display the window
- UpdateCommandSources();
- Show();
- SetCallMode(IdleCallMode);
- speakerphoneSwitch = FALSE;
- // Get some parameters
- autoAnswer = config.GetBoolean(AutoAnswerConfigKey, FALSE);
- dtmfAsString = config.GetBoolean(DtmfAsStringConfigKey, TRUE);
- maxRecentCalls = config.GetInteger(MaxRecentCallsConfigKey, 10);
- noAnswerForwardParty = config.GetString(NoAnswerForwardPartyConfigKey);
- noAnswerTime = PTimeInterval(0, config.GetInteger(NoAnswerTimeConfigKey, 30));
- ringSoundFile = config.GetString(RingSoundFileConfigKey);
- ringSoundTimer.SetNotifier(PCREATE_NOTIFIER(OnRingSoundAgain));
- noAnswerTimer.SetNotifier(PCREATE_NOTIFIER(OnNoAnswerTimeout));
- // Initialisation of H323 stuff
- if (endpoint.Initialise(config)) {
- OutputStatus(IDS_LISTENING);
- endpoint.xJack.SetPlayVolume(OpalIxJDevice::POTSLine, spkrVolume);
- endpoint.xJack.SetRecordVolume(OpalIxJDevice::POTSLine, mikeVolume);
- }
- else
- SetCallMode(NoGatekeeperMode);
- }
- MainWindow::~MainWindow()
- {
- currentCallMode = ApplicationShuttingDown;
- // Do this now, if leave to endpoint destructor callbacks on the main window
- // are accessing destroyed object.
- endpoint.ClearAllCalls();
- #if PTRACING
- if (myTraceFile) {
- PTrace::SetStream(NULL);
- myTraceFile->Close();
- }
- delete myTraceFile;
- #endif
- }
- void MainWindow::OutputStatus(PRESOURCE_ID strId, ...)
- {
- if (currentCallMode == ApplicationShuttingDown)
- return;
- va_list args;
- va_start(args, strId);
- PResourceString fmt = strId;
- PStringArray lines = pvsprintf(fmt, args).Lines();
- for (PINDEX i = 0; i < lines.GetSize(); i++)
- statusWindow->AddString(lines[i]);
- PINDEX count = statusWindow->GetCount();
- if (count > 3)
- statusWindow->SetTopIndex(count - 3);
- }
- BOOL MainWindow::AllowClose(BOOL)
- {
- PWaitAndSignal mutex(callModeMutex);
- switch (currentCallMode) {
- case IdleCallMode :
- case NoGatekeeperMode :
- case ApplicationShuttingDown :
- break;
- default :
- if (!PSimpleDialog::YesNo(this, IDS_INCALLEXIT))
- return FALSE;
- break;
- }
- currentCallMode = ApplicationShuttingDown;
- return TRUE;
- }
- void MainWindow::OnClose()
- {
- PConfig config;
- PPoint pos = GetPosition(PixelCoords);
- config.SetInteger(MainWindowLeftConfigKey, pos.X());
- config.SetInteger(MainWindowTopConfigKey, pos.Y());
- PDim dim = GetDimensions(PixelCoords);
- config.SetInteger(MainWindowWidthConfigKey, dim.Width());
- config.SetInteger(MainWindowHeightConfigKey, dim.Height());
- }
- void MainWindow::OnResize(const PDim & newSize, ResizeType type)
- {
- if (type != Normalised)
- return;
- statusWindow->SetDimensions(newSize.Width(), statusWindow->GetDimensions(PixelCoords).Height(), PixelCoords);
- makeCallButton->SetDimensions(newSize.Width(), makeCallButton->GetDimensions(PixelCoords).Height(), PixelCoords);
- answerButton->SetDimensions(newSize.Width()/2, answerButton->GetDimensions(PixelCoords).Height(), PixelCoords);
- refuseButton->SetDimensions(newSize.Width()/2, refuseButton->GetDimensions(PixelCoords).Height(), PixelCoords);
- refuseButton->SetPosition(newSize.Width()/2, refuseButton->GetPosition(PixelCoords).Y(), TopLeftPixels, TopLeftPixels);
- hangUpButton->SetDimensions(newSize.Width()/2, hangUpButton->GetDimensions(PixelCoords).Height(), PixelCoords);
- speakerButton->SetDimensions(newSize.Width()/2, speakerButton->GetDimensions(PixelCoords).Height(), PixelCoords);
- speakerButton->SetPosition(newSize.Width()/2, speakerButton->GetPosition(PixelCoords).Y(), TopLeftPixels, TopLeftPixels);
- PDIMENSION scrollBarWidth = newSize.Width()/2-speakerEnable->GetDimensions(PixelCoords).Width();
- speakerVolume->SetDimensions(scrollBarWidth, speakerVolume->GetDimensions(PixelCoords).Height(), PixelCoords);
- speakerEnable->SetPosition(scrollBarWidth, speakerEnable->GetPosition(PixelCoords).Y(), TopLeftPixels, TopLeftPixels);
- scrollBarWidth = newSize.Width()/2-microphoneEnable->GetDimensions(PixelCoords).Width();
- microphoneVolume->SetDimensions(scrollBarWidth, microphoneVolume->GetDimensions(PixelCoords).Height(), PixelCoords);
- microphoneVolume->SetPosition(newSize.Width()/2, microphoneVolume->GetPosition(PixelCoords).Y(), TopLeftPixels, TopLeftPixels);
- microphoneEnable->SetPosition(newSize.Width()/2+scrollBarWidth, microphoneEnable->GetPosition(PixelCoords).Y(), TopLeftPixels, TopLeftPixels);
- if (speedDialButtons.IsEmpty())
- return;
- PDim dim = speedDialButtons[0].GetDimensions(PixelCoords);
- PORDINATE top = speedDialButtons[0].GetPosition(PixelCoords).Y();
- PORDINATE x = 0;
- PORDINATE y = top;
- for (PINDEX i = 0; i < speedDialButtons.GetSize(); i++) {
- if ((PDIMENSION)y+dim.Height() > newSize.Height()) {
- y = top;
- x += dim.Width();
- if ((PDIMENSION)x+dim.Width()/2 > newSize.Width())
- break;
- }
- speedDialButtons[i].SetPosition(x, y, TopLeftPixels, TopLeftPixels);
- y += dim.Height();
- }
- }
- void MainWindow::SetCallMode(CallMode mode)
- {
- PWaitAndSignal mutex(callModeMutex);
- if (currentCallMode == ApplicationShuttingDown)
- return;
- currentCallMode = mode;
- if (currentCallMode == ApplicationShuttingDown)
- return;
- makeCallButton->Show(mode == IdleCallMode ||
- mode == HangingUpMode ||
- mode == ActiveLineCallMode ||
- mode == NoGatekeeperMode);
- makeCallButton->Enable(mode == IdleCallMode);
- for (PINDEX i = 0; i < speedDialButtons.GetSize(); i++)
- speedDialButtons[i].Show(mode == IdleCallMode);
- answerButton->Show(mode == IncomingCallWait);
- refuseButton->Show(mode == IncomingCallWait);
- BOOL inCall = mode == MakingCallMode ||
- mode == Active323CallMode ||
- mode == ActiveLineCallMode;
- hangUpButton->Show(inCall);
- speakerButton->Show(inCall);
- speakerButton->Enable(mode == Active323CallMode &&
- endpoint.xJack.IsLineOffHook(OpalIxJDevice::POTSLine));
- myMainMenu->ind1->Enable(inCall);
- myMainMenu->ind2->Enable(inCall);
- myMainMenu->ind3->Enable(inCall);
- myMainMenu->ind4->Enable(inCall);
- myMainMenu->ind5->Enable(inCall);
- myMainMenu->ind6->Enable(inCall);
- myMainMenu->ind7->Enable(inCall);
- myMainMenu->ind8->Enable(inCall);
- myMainMenu->ind9->Enable(inCall);
- myMainMenu->ind0->Enable(inCall);
- myMainMenu->inds->Enable(inCall);
- myMainMenu->indh->Enable(inCall);
- if (!inCall)
- statisticsDialog->Hide();
- speakerEnable->Show(mode == Active323CallMode);
- speakerVolume->Show(mode == Active323CallMode);
- microphoneEnable->Show(mode == Active323CallMode);
- microphoneVolume->Show(mode == Active323CallMode);
- speakerVolume->Enable(endpoint.xJack.IsOpen());
- microphoneVolume->Enable(endpoint.xJack.IsOpen());
- }
- void MainWindow::OnCallButton(PTextButton &, INT)
- {
- CallCmd();
- }
- void MainWindow::CallCmd()
- {
- if (!CanMakeCall())
- return;
- PConfig config(RecentCallsConfigSection);
- MakeCallDialog dlg(this); // ask the user what address to call
- dlg.recentCalls.SetSize(maxRecentCalls);
- PINDEX i;
- for (i = 0; i < maxRecentCalls; i++) {
- dlg.recentCalls[i] = -1;
- PString fullAddress = config.GetString(psprintf("%u", i+1));
- if (!fullAddress) {
- PINDEX at = fullAddress.Find('@');
- if (at == P_MAX_INDEX)
- dlg.addressBox->AddString(fullAddress);
- else {
- dlg.addressBox->AddString(fullAddress.Left(at));
- dlg.recentCalls[i] = dlg.gatewayBox->AddString(fullAddress.Mid(at+1));
- }
- }
- }
- if (endpoint.xJack.IsLinePresent(OpalIxJDevice::PSTNLine))
- dlg.gatewayBox->AddString(InternalGatewayName);
- dlg.AddressChanged(*dlg.addressBox, PComboBox::EditChange);
- if (!dlg.RunModal())
- return;
- for (i = 0; i < dlg.gatewayBox->GetCount(); i++) {
- if (dlg.address == dlg.gatewayBox->GetString(i))
- break;
- }
- if (i >= dlg.gatewayBox->GetCount()) {
- PINDEX count = dlg.addressBox->GetCount();
- if (count >= maxRecentCalls-1)
- count = maxRecentCalls-1;
- for (i = count; i > 0; i--)
- config.SetString(psprintf("%u", i+1), config.GetString(psprintf("%u", i)));
- if (dlg.gateway.IsEmpty())
- config.SetString("1", dlg.address);
- else
- config.SetString("1", dlg.address + '@' + dlg.gateway);
- }
- MakeCall(dlg.address, dlg.gateway);
- }
- BOOL MainWindow::CanMakeCall()
- {
- return currentCallMode == IdleCallMode;
- }
- void MakeCallDialog::AddressChanged(PComboBox & box, INT status)
- {
- if (status != PComboBox::NewSelection)
- ok->Enable(box.GetLength() > 0);
- else {
- PINDEX idx = box.GetCurrent();
- if (idx >= recentCalls.GetSize() || recentCalls[idx] < 0)
- gatewayBox->SetText("");
- else {
- gatewayBox->SetCurrent(recentCalls[idx]);
- gateway = gatewayBox->GetString(recentCalls[idx]);
- }
- ok->Enable();
- }
- }
- void MainWindow::HangupCmd()
- {
- if (!CanHangupCall())
- return;
- endpoint.xJack.StopTone(OpalIxJDevice::POTSLine);
- if (currentCallMode == ActiveLineCallMode) {
- endpoint.xJack.SetLineOnHook(OpalIxJDevice::PSTNLine);
- SetCallMode(IdleCallMode);
- }
- else {
- endpoint.ClearCall(currentCallToken);
- SetCallMode(HangingUpMode);
- }
- OutputStatus(IDS_HANGINGUP);
- }
- BOOL MainWindow::CanHangupCall()
- {
- return currentCallMode == MakingCallMode ||
- currentCallMode == Active323CallMode ||
- currentCallMode == ActiveLineCallMode;
- }
- void MainWindow::OnHangUpButton(PTextButton &, INT)
- {
- HangupCmd();
- }
- void MainWindow::OnSpeakerButton(PTextButton &, INT)
- {
- speakerphoneSwitch = TRUE;
- speakerButton->Disable();
- OutputStatus(IDS_REPLACEHANDSET);
- endpoint.xJack.DisableAudio(OpalIxJDevice::POTSLine);
- }
- void MainWindow::AcceptCallCmd()
- {
- AnswerCall(TRUE);
- }
- BOOL MainWindow::CanAcceptCall()
- {
- return currentCallMode == IncomingCallWait;
- }
- void MainWindow::OnAnswerButton(PTextButton &, INT)
- {
- AcceptCallCmd();
- }
- void MainWindow::RefuseCallCmd()
- {
- AnswerCall(FALSE);
- }
- BOOL MainWindow::CanRefuseCall()
- {
- return currentCallMode == IncomingCallWait;
- }
- void MainWindow::OnRefuseButton(PTextButton &, INT)
- {
- RefuseCallCmd();
- }
- void MainWindow::UserInputCmd(PMenuItem & item, INT)
- {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection == NULL)
- return;
- PString tone = item.GetString().Left(1);
- OutputStatus(IDS_SENDINGTONE, (const char *)tone);
- if (dtmfAsString)
- connection->SendUserInput(tone);
- else
- connection->SendUserInputTone(tone[0]);
- connection->Unlock();
- }
- void MainWindow::ShowStatsCmd()
- {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection == NULL)
- return;
- RTP_Session * session = connection->GetSession(RTP_Session::DefaultAudioSessionID);
- if (session != NULL)
- endpoint.OnRTPStatistics(*connection, *session);
- connection->Unlock();
- statisticsDialog->Show();
- }
- BOOL MainWindow::CanShowStats()
- {
- return currentCallMode == Active323CallMode;
- }
- void MainWindow::OnMicrophoneEnable(PCheckBox &, INT)
- {
- MuteMicrophoneCmd();
- }
- void MainWindow::MuteMicrophoneCmd()
- {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection == NULL)
- return;
- H323Channel * channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, FALSE);
- if (channel != NULL) {
- BOOL newState = !channel->IsPaused();
- channel->SetPause(newState);
- microphoneEnable->SetValue(!newState);
- }
- connection->Unlock();
- }
- BOOL MainWindow::CanMuteMicrophone()
- {
- return currentCallMode == Active323CallMode;
- }
- void MainWindow::OnSpeakerEnable(PCheckBox &, INT)
- {
- MuteSpeakerCmd();
- }
- void MainWindow::MuteSpeakerCmd()
- {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection == NULL)
- return;
- H323Channel * channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, TRUE);
- if (channel != NULL) {
- BOOL newState = !channel->IsPaused();
- channel->SetPause(newState);
- speakerEnable->SetValue(!newState);
- }
- connection->Unlock();
- }
- BOOL MainWindow::CanMuteSpeaker()
- {
- return currentCallMode == Active323CallMode;
- }
- void MainWindow::OnSpeakerVolume(PHorizontalScrollBar & bar, INT status)
- {
- endpoint.xJack.SetPlayVolume(OpalIxJDevice::POTSLine, bar.GetValue());
- if (status == PScrollBar::EndTrack) {
- PConfig config;
- config.SetInteger(SpeakerVolumeConfigKey, bar.GetValue());
- }
- }
- void MainWindow::OnMicrophoneVolume(PHorizontalScrollBar & bar, INT status)
- {
- endpoint.xJack.SetRecordVolume(OpalIxJDevice::POTSLine, bar.GetValue());
- if (status == PScrollBar::EndTrack) {
- PConfig config;
- config.SetInteger(MicrophoneVolumeConfigKey, bar.GetValue());
- }
- }
- void MainWindow::ExitCmd()
- {
- owner->Terminate();
- }
- void MainWindow::OnSpeedDialButton(PTextButton & button, INT)
- {
- SpeedDial(button.GetName());
- }
- void MainWindow::AddSpeedDialButtons()
- {
- PConfig config(SpeedDialConfigSection);
- PINDEX i;
- speedDialButtons.RemoveAll();
- PStringList aliases = config.GetKeys();
- for (i = 0; i < aliases.GetSize(); i++) {
- PTextButton * button = new PTextButton(this, aliases[i]);
- button->SetNotifier(PCREATE_NOTIFIER(OnSpeedDialButton));
- speedDialButtons.Append(button);
- }
- PDIMENSION maxWidth = 0;
- for (i = 0; i < speedDialButtons.GetSize(); i++) {
- PDIMENSION width = speedDialButtons[i].GetDimensions(LocalCoords).Width();
- if (maxWidth < width)
- maxWidth = width;
- }
- for (i = 0; i < speedDialButtons.GetSize(); i++) {
- speedDialButtons[i].SetDimensions(maxWidth, SpeedDialButtonHeight, LocalCoords);
- speedDialButtons[i].SetPosition(0, StatusWindowHeight+CallButtonHeight);
- speedDialButtons[i].Show();
- }
- OnResize(GetDimensions(PixelCoords), Normalised);
- }
- void MainWindow::SpeedDialOptionsCmd()
- {
- SpeedDialOptionDlg dlg(this);
- PConfig config(SpeedDialConfigSection);
- PINDEX i;
- PStringList aliases = config.GetKeys();
- for (i = 0; i < aliases.GetSize(); i++)
- dlg.speedDialList->AddString(aliases[i]+'t'+config.GetString(aliases[i]));
- dlg.selectedSpeedDial = P_MAX_INDEX;
- if (!dlg.RunModal())
- return;
- config.DeleteSection();
- for (i = 0; i < dlg.speedDialList->GetCount(); i++) {
- PString str = dlg.speedDialList->GetString(i);
- PINDEX tab = str.Find('t');
- config.SetString(str.Left(tab), str.Mid(tab+1));
- }
- AddSpeedDialButtons();
- }
- void SpeedDialOptionDlg::AddButton(PTextButton &, INT)
- {
- speedDialList->AddString(alias+'t'+address+'t'+gateway);
- alias = address = gateway;
- UpdateControls();
- EnableFields();
- }
- void SpeedDialOptionDlg::RemoveButton(PTextButton &, INT)
- {
- PString str = speedDialList->GetString(selectedSpeedDial);
- PINDEX tab1 = str.Find('t');
- PINDEX tab2 = str.Find('t', tab1+1);
- alias = str.Left(tab1);
- address = str(tab1+1, tab2-1);
- gateway = str.Mid(tab2+1);
- speedDialList->DeleteEntry(selectedSpeedDial);
- selectedSpeedDial = P_MAX_INDEX;
- UpdateControls();
- EnableFields();
- }
- void SpeedDialOptionDlg::UpButton(PTextButton &, INT)
- {
- PINDEX selection = selectedSpeedDial;
- speedDialList->InsertString(speedDialList->GetString(selection), selection-1, FALSE);
- speedDialList->DeleteEntry(selection+1);
- speedDialList->SetSelection(selection-1);
- }
- void SpeedDialOptionDlg::DownButton(PTextButton &, INT)
- {
- PINDEX selection = selectedSpeedDial;
- speedDialList->InsertString(speedDialList->GetString(selection), selection+2, FALSE);
- speedDialList->DeleteEntry(selection);
- speedDialList->SetSelection(selection+1);
- }
- void SpeedDialOptionDlg::SpeedDialSelect(PStringListBox &, INT)
- {
- EnableFields();
- }
- void SpeedDialOptionDlg::AddressChanged(PEditBox &, INT)
- {
- EnableFields();
- }
- void SpeedDialOptionDlg::EnableFields()
- {
- addButton->Enable(!alias);
- PINDEX count = speedDialList->GetCount();
- removeButton->Enable(selectedSpeedDial < count);
- upButton->Enable(selectedSpeedDial > 0 && selectedSpeedDial < count);
- downButton->Enable(selectedSpeedDial < count-1);
- }
- void MainWindow::GeneralOptionsCmd()
- {
- PConfig config;
- GeneralOptionsDlg dlg(this);
- dlg.username = endpoint.GetLocalUserName();
- const PStringList & aliases = endpoint.GetAliasNames();
- PINDEX i;
- for (i = 1; i < aliases.GetSize(); i++)
- dlg.aliasList->AddString(aliases[i]);
- dlg.addAliasBtn->Disable();
- dlg.delAliasBtn->Disable();
- dlg.bandwidthType = config.GetInteger(BandwidthTypeConfigKey, 5);
- dlg.bandwidth = endpoint.GetInitialBandwidth()/20.0;
- dlg.bandwidthBox->Enable(dlg.bandwidthType == 6);
- dlg.maxRecentCalls = maxRecentCalls;
- dlg.ipTOS = endpoint.GetRtpIpTypeofService();
- dlg.ringSoundFile = ringSoundFile;
- dlg.playSoundButton->Enable(!ringSoundFile);
- dlg.dtmfAsString = dtmfAsString;
- dlg.autoAnswer = autoAnswer;
- dlg.noFastStart = endpoint.noFastStart;
- dlg.noTunneling = endpoint.noTunneling;
- if (!dlg.RunModal())
- return;
- endpoint.SetLocalUserName(dlg.username);
- config.SetString(UsernameConfigKey, dlg.username);
- for (i = 0; i < dlg.aliasList->GetCount(); i++) {
- PString alias = dlg.aliasList->GetString(i);
- endpoint.AddAliasName(alias);
- config.SetString(psprintf(AliasConfigKey, i), alias);
- }
- config.DeleteKey(psprintf(AliasConfigKey, i));
- autoAnswer = dlg.autoAnswer;
- config.SetBoolean(AutoAnswerConfigKey, autoAnswer);
- dtmfAsString = dlg.dtmfAsString;
- config.SetBoolean(DtmfAsStringConfigKey, dtmfAsString);
- endpoint.noFastStart = dlg.noFastStart;
- config.SetBoolean(NoFastStartConfigKey, dlg.noFastStart);
- endpoint.noTunneling = dlg.noTunneling;
- config.SetBoolean(NoTunnelingConfigKey, dlg.noTunneling);
- endpoint.SetInitialBandwidth((unsigned)(dlg.bandwidth*20));
- config.SetReal(BandwidthConfigKey, dlg.bandwidth);
- config.SetInteger(BandwidthTypeConfigKey, dlg.bandwidthType);
- maxRecentCalls = dlg.maxRecentCalls;
- config.SetInteger(MaxRecentCallsConfigKey, maxRecentCalls);
- endpoint.SetRtpIpTypeofService(dlg.ipTOS);
- config.SetInteger(IpTosConfigKey, dlg.ipTOS);
- ringSoundFile = dlg.ringSoundFile;
- config.SetString(RingSoundFileConfigKey, ringSoundFile);
- }
- void GeneralOptionsDlg::ChangedUsername(PEditBox & box, INT)
- {
- ok->Enable(box.GetLength() > 0);
- }
- void GeneralOptionsDlg::ChangedAlias(PEditBox & box, INT)
- {
- addAliasBtn->Enable(box.GetLength() > 0);
- }
- void GeneralOptionsDlg::AddAlias(PTextButton &, INT)
- {
- aliasList->AddString(alias);
- alias = PString();
- UpdateControls();
- }
- void GeneralOptionsDlg::DelAlias(PTextButton &, INT)
- {
- alias = aliasList->GetSelectedString();
- aliasList->DeleteString(aliasList->GetSelection());
- UpdateControls();
- }
- void GeneralOptionsDlg::SelectAlias(PStringListBox & box, INT)
- {
- delAliasBtn->Enable(box.GetSelection() != P_MAX_INDEX);
- }
- void GeneralOptionsDlg::BandwidthChange(PChoiceBox &, INT)
- {
- bandwidthBox->Enable(bandwidthType == 6);
- if (bandwidthType < 6) {
- static int const bandwidths[6] = {
- 14400, 28800, 64000, 128000, 1500000, 10000000
- };
- bandwidth = bandwidths[bandwidthType]/1000.0;
- UpdateControls();
- }
- }
- void GeneralOptionsDlg::ChangedSoundFile(PEditBox & box, INT)
- {
- playSoundButton->Enable(box.GetLength() > 0);
- }
- void GeneralOptionsDlg::BrowseSound(PTextButton &, INT)
- {
- POpenFileDialog dlg(this);
- dlg.AddFileType(".wav");
- if (dlg.RunModal()) {
- ringSoundFile = dlg.GetFile();
- UpdateControls();
- }
- }
- void GeneralOptionsDlg::PlaySoundFile(PTextButton &, INT)
- {
- PSound::PlayFile(ringSoundFile, FALSE);
- }
- void MainWindow::ForwardingOptionsCmd()
- {
- PConfig config;
- ForwardingOptionsDlg dlg(this);
- dlg.alwaysForwardParty = endpoint.alwaysForwardParty;
- dlg.busyForwardParty = endpoint.busyForwardParty;
- dlg.noAnswerForwardParty = noAnswerForwardParty;
- dlg.noAnswerTime = noAnswerTime.GetSeconds();
- if (!dlg.RunModal())
- return;
- endpoint.alwaysForwardParty = dlg.alwaysForwardParty;
- config.SetString(AlwaysForwardPartyConfigKey, endpoint.alwaysForwardParty);
- endpoint.busyForwardParty = dlg.busyForwardParty;
- config.SetString(BusyForwardPartyConfigKey, endpoint.busyForwardParty);
- noAnswerForwardParty = dlg.noAnswerForwardParty;
- config.SetString(NoAnswerForwardPartyConfigKey, noAnswerForwardParty);
- noAnswerTime = PTimeInterval(0, dlg.noAnswerTime);
- config.SetInteger(NoAnswerTimeConfigKey, dlg.noAnswerTime);
- }
- void MainWindow::GatekeeperOptionsCmd()
- {
- GatekeeperOptionsDlg dlg(this);
- PConfig config;
- dlg.useGatekeeper = config.GetBoolean(UseGatekeeperConfigKey, FALSE);
- dlg.gatekeeperHost = config.GetString(GatekeeperHostConfigKey);
- dlg.discover = dlg.gatekeeperHost.IsEmpty() ? 1 : 2;
- dlg.requireGatekeeper = config.GetBoolean(RequireGatekeeperConfigKey, FALSE);
- dlg.EnableFields();
- if (!dlg.RunModal())
- return;
- config.SetBoolean(UseGatekeeperConfigKey, dlg.useGatekeeper);
- if (dlg.discover == 1)
- config.SetString(GatekeeperHostConfigKey, "");
- else
- config.SetString(GatekeeperHostConfigKey, dlg.gatekeeperHost);
- config.SetBoolean(RequireGatekeeperConfigKey, dlg.requireGatekeeper);
- if (endpoint.FindGatekeeper(config))
- SetCallMode(IdleCallMode);
- else
- SetCallMode(NoGatekeeperMode);
- }
- BOOL MainWindow::CanSetGatekeeper()
- {
- return currentCallMode == IdleCallMode ||
- currentCallMode == NoGatekeeperMode;
- }
- void GatekeeperOptionsDlg::UsingGatekeeper(PCheckBox &, INT)
- {
- EnableFields();
- }
- void GatekeeperOptionsDlg::CheckDiscover(PRadioButton &, INT)
- {
- EnableFields();
- }
- void GatekeeperOptionsDlg::EnableFields()
- {
- discoverButton->Enable(useGatekeeper);
- staticGkButton->Enable(useGatekeeper);
- gatekeeperHostBox->Enable(useGatekeeper && discover == 2);
- requireBox->Enable(useGatekeeper);
- }
- void MainWindow::AudioOptionsCmd()
- {
- PConfig config;
- AudioOptionsDlg dlg(this);
- dlg.cardSelection = endpoint.xJack.IsOpen() ? 2 : 1;
- PINDEX i;
- PStringArray playDevices = PSoundChannel::GetDeviceNames(PSoundChannel::Player);
- for (i = 0; i < playDevices.GetSize(); i++)
- dlg.playDeviceBox->AddString(playDevices[i]);
- dlg.playSoundDevice = dlg.playDeviceBox->FindString(endpoint.GetSoundChannelPlayDevice());
- PStringArray recordDevices = PSoundChannel::GetDeviceNames(PSoundChannel::Recorder);
- for (i = 0; i < recordDevices.GetSize(); i++)
- dlg.recordDeviceBox->AddString(recordDevices[i]);
- dlg.recordSoundDevice = dlg.recordDeviceBox->FindString(endpoint.GetSoundChannelRecordDevice());
- dlg.soundBuffers = endpoint.GetSoundChannelBufferDepth();
- PStringArray xJackDevices = OpalIxJDevice::GetDeviceNames();
- dlg.quickNetButton->Enable(!xJackDevices.IsEmpty());
- for (i = 0; i < xJackDevices.GetSize(); i++)
- dlg.xJackDeviceBox->AddString(xJackDevices[i]);
- PINDEX previousDevice;
- PStringArray devices = OpalIxJDevice::GetDeviceNames();
- if (devices.GetSize() == 0)
- previousDevice = 0;
- else {
- previousDevice = dlg.xJackDeviceBox->FindString(config.GetString(QuicknetDeviceConfigKey, devices[0]));
- if (previousDevice == P_MAX_INDEX)
- previousDevice = 0;
- }
- dlg.xJackDevice = previousDevice;
- dlg.aecLevel = config.GetInteger(AECConfigKey, 2);
- dlg.silenceDetect = endpoint.silenceDetect;
- i = 0;
- for (;;) {
- PString key = psprintf(CodecsConfigKey, ++i);
- PString name = config.GetString(CodecsConfigSection, key, "");
- if (name.IsEmpty())
- break;
- dlg.codecList->AddString(name);
- }
- dlg.SelectCodec(*dlg.codecList, 0);
- dlg.enabledCodec->Disable();
- dlg.packetSizeBox->Disable();
- dlg.jitter = endpoint.GetMaxAudioDelayJitter();
- dlg.SelectCard(*(PRadioButton *)NULL, 0);
- if (!dlg.RunModal())
- return;
- config.SetBoolean(UseQuicknetConfigKey, dlg.cardSelection == 2);
- if (dlg.cardSelection == 1 && endpoint.xJack.IsOpen())
- endpoint.CloseQuicknet();
- PString str = dlg.playDeviceBox->GetString(dlg.playSoundDevice);
- config.SetString(SoundPlayConfigKey, str);
- endpoint.SetSoundChannelPlayDevice(str);
- str = dlg.recordDeviceBox->GetString(dlg.recordSoundDevice);
- config.SetString(SoundRecordConfigKey, str);
- endpoint.SetSoundChannelRecordDevice(str);
- config.SetInteger(SoundBuffersConfigKey, dlg.soundBuffers);
- endpoint.SetSoundChannelBufferDepth(dlg.soundBuffers);
- str = dlg.xJackDeviceBox->GetString(dlg.xJackDevice);
- config.SetString(QuicknetDeviceConfigKey, str);
- config.SetInteger(SoundBuffersConfigKey, dlg.soundBuffers);
- config.SetInteger(AECConfigKey, dlg.aecLevel);
- endpoint.xJack.SetAEC(OpalIxJDevice::POTSLine, (OpalIxJDevice::AECLevels)dlg.aecLevel);
- endpoint.silenceDetect = dlg.silenceDetect;
- config.SetBoolean(SilenceDetectConfigKey, dlg.silenceDetect);
- if (GetCallMode() == Active323CallMode) {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection != NULL) {
- H323Channel * channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, FALSE);
- if (channel != NULL) {
- H323Codec * codec = channel->GetCodec();
- if (codec != NULL && codec->IsDescendant(H323AudioCodec::Class())) {
- H323AudioCodec::SilenceDetectionMode newMode =
- dlg.silenceDetect ? H323AudioCodec::AdaptiveSilenceDetection
- : H323AudioCodec::NoSilenceDetection;
- if (((H323AudioCodec*)codec)->GetSilenceDetectionMode() != newMode)
- ((H323AudioCodec*)codec)->SetSilenceDetectionMode(newMode);
- }
- }
- connection->Unlock();
- }
- }
- if (dlg.cardSelection == 2 && (!endpoint.xJack.IsOpen() || dlg.xJackDevice != previousDevice))
- endpoint.OpenQuicknet(config);
- endpoint.SetMaxAudioDelayJitter(dlg.jitter);
- config.SetInteger(JitterConfigKey, dlg.jitter);
- PString oldSection = config.GetDefaultSection();
- config.SetDefaultSection(CodecsConfigSection);
- config.DeleteSection();
- for (i = 0; i < dlg.codecList->GetCount(); i++)
- config.SetString(psprintf(CodecsConfigKey, i+1), dlg.codecList->GetString(i));
- config.SetDefaultSection(oldSection);
- endpoint.LoadCapabilities(config);
- }
- void AudioOptionsDlg::SelectCard(PRadioButton &, INT)
- {
- playDeviceTitle->Enable(cardSelection == 1);
- playDeviceBox->Enable(cardSelection == 1);
- recordDeviceTitle->Enable(cardSelection == 1);
- recordDeviceBox->Enable(cardSelection == 1);
- soundBuffersTitle->Enable(cardSelection == 1);
- soundBuffersBox->Enable(cardSelection == 1);
- xJackDeviceTitle->Enable(cardSelection == 2);
- xJackDeviceBox->Enable(cardSelection == 2);
- aecTitle->Enable(cardSelection == 2);
- aecBox->Enable(cardSelection == 2);
- }
- void AudioOptionsDlg::SelectCodec(PStringListBox & list, INT)
- {
- PINDEX selection = list.GetSelection();
- PINDEX count = list.GetCount();
- up->Enable(selection > 0 && selection < count);
- down->Enable(selection < count-1);
- enabledCodec->Enable(selection < count);
- packetSizeBox->Enable(selection < count);
- PString value = list.GetString(selection);
- enabledCodec->SetValue(value.Find(OffCodecSuffix) == P_MAX_INDEX);
- PINDEX left = value.FindLast('[');
- PINDEX right = value.FindLast(']');
- if (left != P_MAX_INDEX && right != P_MAX_INDEX)
- packetSizeBox->SetValue(value(left+1, right-1).AsUnsigned());
- }
- void AudioOptionsDlg::MoveUp(PTextButton &, INT)
- {
- PINDEX selection = codecList->GetSelection();
- codecList->InsertString(codecList->GetString(selection), selection-1, FALSE);
- codecList->DeleteEntry(selection+1);
- codecList->SetSelection(selection-1);
- }
- void AudioOptionsDlg::MoveDown(PTextButton &, INT)
- {
- PINDEX selection = codecList->GetSelection();
- codecList->InsertString(codecList->GetString(selection), selection+2, FALSE);
- codecList->DeleteEntry(selection);
- codecList->SetSelection(selection+1);
- }
- void AudioOptionsDlg::EnableCodec(PCheckBox & box, INT)
- {
- PINDEX selection = codecList->GetSelection();
- if (selection == P_MAX_INDEX)
- return;
- PString str = codecList->GetString(selection);
- if (box.GetValue())
- str.Replace(OffCodecSuffix, OnCodecSuffix);
- else
- str.Replace(OnCodecSuffix, OffCodecSuffix);
- codecList->SetString(str, selection);
- codecList->SetSelection(selection);
- }
- void AudioOptionsDlg::PacketSizeChange(PIntegerEditBox & box, INT code)
- {
- if (code != PEditBox::EndEdit)
- return;
- PINDEX selection = codecList->GetSelection();
- if (selection == P_MAX_INDEX)
- return;
- PString str = codecList->GetString(selection);
- PINDEX left = str.FindLast('[');
- PINDEX right = str.FindLast(']');
- if (left != P_MAX_INDEX && right != P_MAX_INDEX) {
- str.Splice(psprintf("%u", box.GetValue()), left+1, right-left-1);
- codecList->SetString(str, selection);
- codecList->SetSelection(selection);
- }
- }
- void MainWindow::VideoOptionsCmd()
- {
- PConfig config;
- VideoOptionsDlg dlg(this);
- dlg.rxqcif = config.GetBoolean(H261QCIFConfigKey, TRUE);
- dlg.rxcif = config.GetBoolean(H261CIFConfigKey, TRUE);
- dlg.rxauto = config.GetBoolean(AutoReceiveVideoConfigKey, TRUE);
- dlg.txsize = config.GetInteger(VideoSizeConfigKey, 1);
- dlg.source = config.GetInteger(VideoSourceConfigKey, 1);
- dlg.format = config.GetInteger(VideoFormatConfigKey, 1);
- dlg.quality = config.GetInteger(VideoQualityConfigKey, 15);
- if (!dlg.RunModal())
- return;
- config.SetBoolean(H261QCIFConfigKey, dlg.rxqcif);
- config.SetBoolean(H261CIFConfigKey, dlg.rxcif);
- config.SetBoolean(AutoReceiveVideoConfigKey, dlg.rxauto);
- config.SetInteger(VideoSizeConfigKey, dlg.txsize);
- config.SetInteger(VideoSourceConfigKey, dlg.source);
- config.SetInteger(VideoFormatConfigKey, dlg.format);
- config.SetInteger(VideoQualityConfigKey, dlg.quality);
- endpoint.LoadCapabilities(config);
- }
- #if PTRACING
- void MainWindow::TraceOptionsCmd()
- {
- TraceOptionsDlg dlg(this);
- PConfig config;
- dlg.traceFlag = myTraceFile != NULL; // tracing has been enabled
- if (myTraceFile != NULL)
- dlg.traceFile = myTraceFile->GetName();
- else
- dlg.traceFile = PFilePath("trace.txt");
- dlg.traceLevel = PTrace::GetLevel();
- dlg.traceBlocks = (PTrace::GetOptions()&PTrace::Blocks) != 0;
- dlg.dateAndTime = (PTrace::GetOptions()&PTrace::DateAndTime) != 0;
- dlg.timestamp = (PTrace::GetOptions()&PTrace::Timestamp) != 0;
- dlg.threads = (PTrace::GetOptions()&PTrace::Thread) != 0;
- dlg.threadAddr = (PTrace::GetOptions()&PTrace::ThreadAddress) != 0;
- dlg.levelDisplay = (PTrace::GetOptions()&PTrace::TraceLevel) != 0;
- dlg.fileAndLine = (PTrace::GetOptions()&PTrace::FileAndLine) != 0;
- dlg.TraceSet(*(PCheckBox *)NULL, 0);
- if (!dlg.RunModal())
- return;
- if (dlg.traceFlag)
- config.SetString(TraceFileConfigKey, dlg.traceFile);
- else
- config.SetString(TraceFileConfigKey, "");
- config.SetInteger(TraceLevelConfigKey, dlg.traceLevel);
- config.SetBoolean(TraceBlockConfigKey, dlg.traceBlocks);
- config.SetBoolean(TraceDateTimeConfigKey, dlg.dateAndTime);
- config.SetBoolean(TraceTimestampConfigKey, dlg.timestamp);
- config.SetBoolean(TraceThreadsConfigKey, dlg.threads);
- config.SetBoolean(TraceThreadAddresssConfigKey, dlg.threadAddr);
- config.SetBoolean(TraceLevelDisplayConfigKey, dlg.levelDisplay);
- config.SetBoolean(TraceFileLineConfigKey, dlg.fileAndLine);
- OpenTraceFile(config);
- }
- void TraceOptionsDlg::TraceSet(PCheckBox &, INT)
- {
- traceLevelText->Enable(traceFlag);
- traceLevelBox->Enable(traceFlag);
- traceOutText->Enable(traceFlag);
- traceOutBox->Enable(traceFlag);
- traceBlocksBox->Enable(traceFlag);
- dateAndTimeBox->Enable(traceFlag);
- timestampBox->Enable(traceFlag);
- threadsBox->Enable(traceFlag);
- threadAddrBox->Enable(traceFlag);
- levelDisplayBox->Enable(traceFlag);
- fileAndLineBox->Enable(traceFlag);
- }
- static void SetTraceOption(PConfig & config, const char * key, unsigned option)
- {
- if (config.GetBoolean(key))
- PTrace::SetOptions(option);
- else
- PTrace::ClearOptions(option);
- }
- BOOL MainWindow::OpenTraceFile(PConfig & config)
- {
- PTrace::SetLevel(config.GetInteger(TraceLevelConfigKey, 1));
- SetTraceOption(config, TraceBlockConfigKey, PTrace::Blocks);
- SetTraceOption(config, TraceDateTimeConfigKey, PTrace::DateAndTime);
- SetTraceOption(config, TraceTimestampConfigKey, PTrace::Timestamp);
- SetTraceOption(config, TraceThreadsConfigKey, PTrace::Thread);
- SetTraceOption(config, TraceThreadAddresssConfigKey, PTrace::ThreadAddress);
- SetTraceOption(config, TraceLevelDisplayConfigKey, PTrace::TraceLevel);
- SetTraceOption(config, TraceFileLineConfigKey, PTrace::FileAndLine);
- PString traceFileName = config.GetString(TraceFileConfigKey);
- // If already have a trace file, see if need to close it
- if (myTraceFile != NULL) {
- // If no change, do nothing more
- if (myTraceFile->GetFilePath() == PFilePath(traceFileName))
- return TRUE;
- PTrace::SetStream(NULL);
- delete myTraceFile;
- myTraceFile = NULL;
- }
- // Have stopped
- if (traceFileName.IsEmpty())
- return TRUE;
- PTextFile * traceFile = new PTextFile;
- if (traceFile->Open(traceFileName, PFile::WriteOnly)) {
- myTraceFile = traceFile;
- PTrace::SetStream(traceFile);
- PProcess & process = PProcess::Current();
- PTRACE(0, process.GetName()
- << " Version " << process.GetVersion(TRUE)
- << " by " << process.GetManufacturer()
- << " on " << process.GetOSClass() << ' ' << process.GetOSName()
- << " (" << process.GetOSVersion() << '-' << process.GetOSHardware() << ')');
- return TRUE;
- }
- PSimpleDialog::Error(this, IDS_TRACE_FAIL, (const char *)traceFile->GetName());
- delete traceFile;
- return FALSE;
- }
- #endif
- void StatisticsDlg::OnCancel()
- {
- Hide();
- }
- BOOL MainWindow::SpeedDial(const PString & key)
- {
- PConfig config(SpeedDialConfigSection);
- PString str = config.GetString(key);
- if (str.IsEmpty())
- return FALSE;
- PINDEX tab = str.Find('t');
- if (tab != P_MAX_INDEX)
- return MakeCall(str.Left(tab), str.Mid(tab+1));
- else
- return MakeCall(str, "");
- }
- BOOL MainWindow::MakeCall(const PString & address, const PString & gateway)
- {
- PString fullAddress = address;
- if (!gateway)
- fullAddress += '@' + gateway;
- OutputStatus(IDS_CALLING, (const char *)fullAddress);
- if (gateway *= InternalGatewayName) {
- if (!endpoint.xJack.IsLinePresent(OpalIxJDevice::PSTNLine))
- return FALSE;
- SetCallMode(ActiveLineCallMode);
- endpoint.xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, TRUE);
- switch (endpoint.xJack.DialOut(OpalIxJDevice::PSTNLine, address)) {
- case OpalLineInterfaceDevice::DialTone :
- OutputStatus(IDS_NODIALTONE);
- break;
- case OpalLineInterfaceDevice::BusyTone :
- OutputStatus(IDS_LINEBUSY, (const char *)address);
- break;
- case OpalLineInterfaceDevice::RingTone :
- OutputStatus(IDS_LINECALLDIALLED);
- break;
- default :
- OutputStatus(IDS_LINECALLFAILED);
- break;
- }
- return TRUE;
- }
- SetCallMode(MakingCallMode);
- endpoint.xJack.PlayTone(OpalIxJDevice::POTSLine, OpalLineInterfaceDevice::RingTone);
- if (endpoint.MakeCall(fullAddress, currentCallToken))
- return TRUE;
- OutputStatus(IDS_INVALIDADDRESS, (const char *)fullAddress);
- SetCallMode(IdleCallMode);
- return FALSE;
- }
- void MainWindow::AnswerCall(BOOL accept)
- {
- if (currentCallMode != IncomingCallWait)
- return;
- endpoint.xJack.RingLine(OpalIxJDevice::POTSLine, 0);
- ringSoundTimer.Stop();
- noAnswerTimer.Stop();
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection == NULL)
- SetCallMode(IdleCallMode);
- else {
- connection->AnsweringCall(accept ? H323Connection::AnswerCallNow
- : H323Connection::AnswerCallDenied);
- connection->Unlock();
- }
- }
- BOOL MainWindow::OnAnswerCall(const PString & token, const PString & caller)
- {
- currentCallToken = token;
- PTime now;
- PString nowStr = now.AsString("w h:m a");
- OutputStatus(IDS_INCOMINGCALL, (const char *)caller, (const char *)nowStr);
- // Check for auto answer option
- if (autoAnswer) {
- SetCallMode(Active323CallMode);
- return TRUE;
- }
- SetCallMode(IncomingCallWait);
- if (endpoint.xJack.IsOpen())
- endpoint.xJack.RingLine(OpalIxJDevice::POTSLine, RingCadence);
- if (!ringSoundFile) {
- PSound::PlayFile(ringSoundFile, FALSE);
- ringSoundTimer.RunContinuous(5000);
- }
- if (!noAnswerForwardParty)
- noAnswerTimer = noAnswerTime;
- return FALSE;
- }
- void MainWindow::OnNoAnswerTimeout(PTimer &, INT)
- {
- H323Connection * connection = endpoint.FindConnectionWithLock(currentCallToken);
- if (connection != NULL) {
- connection->ForwardCall(noAnswerForwardParty);
- connection->Unlock();
- }
- }
- void MainWindow::OnRingSoundAgain(PTimer &, INT)
- {
- if (!ringSoundFile)
- PSound::PlayFile(ringSoundFile, FALSE);
- }
- BOOL MainWindow::OnConnectionForwarded(const PString & forwardParty)
- {
- PTime now;
- PString nowStr = now.AsString("w h:m a");
- OutputStatus(IDS_FORWARDING, (const char *)forwardParty, (const char *)nowStr);
- SetCallMode(MakingCallMode);
- if (MakeCall(forwardParty, ""))
- return TRUE;
- OutputStatus(IDS_INVALIDADDRESS, (const char *)forwardParty);
- SetCallMode(IdleCallMode);
- return FALSE;
- }
- void MainWindow::OnConnectionEstablished(const PString & token, const PString & party)
- {
- currentCallToken = token;
- OutputStatus(IDS_TALKING, (const char *)party);
- SetCallMode(Active323CallMode);
- }
- void MainWindow::OnConnectionCleared(const H323Connection & connection)
- {
- ringSoundTimer.Stop();
- noAnswerTimer.Stop();
- PString remoteParty = connection.GetRemotePartyName();
- if (remoteParty.IsEmpty()) {
- remoteParty = connection.GetControlChannel().GetRemoteAddress();
- if (strncmp(remoteParty, "ip$", 3) == 0) {
- remoteParty.Delete(0, 3);
- remoteParty.Delete(remoteParty.Find(':'), P_MAX_INDEX);
- }
- }
- PStringStream duration;
- duration << setprecision(0) << setw(5)
- << (PTime() - connection.GetConnectionStartTime());
- const char * remoteNameString = remoteParty;
- const char * durationString = duration;
- switch (connection.GetCallEndReason()) {
- case H323Connection::EndedByRemoteUser :
- OutputStatus(IDS_REMOTEHUNGUP, remoteNameString, durationString);
- break;
- case H323Connection::EndedByCallerAbort :
- OutputStatus(IDS_REMOTESTOPPED, remoteNameString);
- break;
- case H323Connection::EndedByRefusal :
- OutputStatus(IDS_REFUSED, remoteNameString);
- break;
- case H323Connection::EndedByNoAnswer :
- OutputStatus(IDS_NOANSWER, remoteNameString);
- break;
- case H323Connection::EndedByTransportFail :
- OutputStatus(IDS_ABNORMAL, remoteNameString, durationString);
- break;
- case H323Connection::EndedByNoUser :
- OutputStatus(IDS_NOUSER, remoteNameString);
- break;
- case H323Connection::EndedByNoBandwidth :
- OutputStatus(IDS_NOBANDWIDTH, remoteNameString);
- break;
- case H323Connection::EndedByCapabilityExchange :
- OutputStatus(IDS_CAPEXCHFAIL, remoteNameString);
- break;
- case H323Connection::EndedByNoAccept :
- case H323Connection::EndedByCallForwarded :
- return; // This is a call busy or forwarded, don't do SetCallMode()
- case H323Connection::EndedByAnswerDenied :
- OutputStatus(IDS_DECLINED, remoteNameString);
- break;
- case H323Connection::EndedByConnectFail :
- switch (connection.GetSignallingChannel()->GetErrorNumber()) {
- case ENETUNREACH :
- OutputStatus(IDS_HOSTUNREACHABLE, remoteNameString);
- break;
- case ETIMEDOUT :
- OutputStatus(IDS_HOSTOFFLINE, remoteNameString);
- break;
- case ECONNREFUSED :
- OutputStatus(IDS_NOENDPOINT, remoteNameString);
- break;
- default :
- OutputStatus(IDS_TRANSPORTERROR, remoteNameString);
- }
- break;
- default :
- OutputStatus(IDS_HUNGUP, remoteNameString, durationString);
- }
- currentCallToken = PString();
- SetCallMode(IdleCallMode);
- }
- void MainWindow::OnLogicalChannel(const H323Channel & channel,
- unsigned txStrID,
- unsigned rxStrID)
- {
- const H323Capability & capability = channel.GetCapability();
- PString name = capability.GetFormatName();
- PString frames;
- if (capability.IsDescendant(H323AudioCapability::Class())) {
- unsigned numFrames = channel.GetDirection() == H323Channel::IsTransmitter
- ? ((H323AudioCapability&)capability).GetTxFramesInPacket()
- : ((H323AudioCapability&)capability).GetRxFramesInPacket();
- numFrames = ((H323AudioCapability&)capability).GetTxFramesInPacket();
- frames.sprintf(" (%u frames)", numFrames);
- }
- switch (channel.GetDirection()) {
- case H323Channel::IsTransmitter :
- OutputStatus(txStrID, (const char *)name, (const char *)frames);
- break;
- case H323Channel::IsReceiver :
- OutputStatus(rxStrID, (const char *)name, (const char *)frames);
- break;
- default :
- break;
- }
- }
- void MainWindow::OnHandsetLifted(OpalIxJDevice & xJack)
- {
- // Are making an outside line call
- if (currentCallMode == ActiveLineCallMode)
- return;
- // Have outside line call coming in
- if (currentCallMode == IncomingLineCall) {
- SetCallMode(ActiveLineCallMode);
- OutputStatus(IDS_USINGOUTSIDELINE);
- return;
- }
- // Stop the ringing
- xJack.RingLine(OpalIxJDevice::POTSLine, 0);
- // Switch audio path to the POTS phone
- xJack.EnableAudio(OpalIxJDevice::POTSLine);
- // Already in a call, or making one, just go to phone set audio
- if (currentCallMode == MakingCallMode || currentCallMode == Active323CallMode) {
- speakerButton->Enable();
- return;
- }
- // Not in call, but have remote party name so must be incoming call.
- if (currentCallMode == IncomingCallWait) {
- AcceptCallCmd();
- return;
- }
- BOOL hasLine = xJack.IsLinePresent(OpalIxJDevice::PSTNLine);
- // Must be in idle state, so bring up dialog for speed dial.
- SpeedDialSelectDlg dlg(this);
- dlg.SetPosition(0, 0, PInteractor::CentreParent, PInteractor::CentreParent);
- if (hasLine)
- dlg.speedDialList->AddString(PResourceString(IDS_OUTSIDELINE));
- for (PINDEX i = 0; i < speedDialButtons.GetSize(); i++) {
- PTextButton & button = (PTextButton &)speedDialButtons[i];
- dlg.speedDialList->AddString(psprintf("%ut", i+1) + button.GetName());
- }
- dlg.ShowAll();
- dlg.Update();
- xJack.PlayTone(OpalIxJDevice::POTSLine, OpalLineInterfaceDevice::DialTone);
- PString digits;
- while (xJack.IsLineOffHook(OpalIxJDevice::POTSLine)) {
- digits += xJack.ReadDTMF(OpalIxJDevice::POTSLine);
- if (!digits)
- xJack.StopTone(OpalIxJDevice::POTSLine);
- if (hasLine && digits == "0") {
- dlg.Hide();
- SetCallMode(ActiveLineCallMode);
- OutputStatus(IDS_USINGOUTSIDELINE);
- xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, TRUE);
- break;
- }
- if (digits.Find('#') != P_MAX_INDEX) {
- PINDEX selection = dlg.speedDialList->GetSelection();
- if (selection == P_MAX_INDEX)
- digits = PString();
- else {
- PString str = dlg.speedDialList->GetString(selection);
- dlg.Hide();
- SpeedDial(str.Mid(str.Find('t')+1));
- break;
- }
- }
- if (digits.Find('*') != P_MAX_INDEX)
- digits = PString();
- dlg.enteredDTMF->SetName(digits);
- dlg.speedDialList->SetSelection(dlg.speedDialList->FindString(digits));
- PThread::Current()->Sleep(100);
- }
- xJack.StopTone(OpalIxJDevice::POTSLine);
- }
- void MainWindow::OnHandsetReturned(OpalIxJDevice & xJack)
- {
- xJack.StopTone(OpalIxJDevice::POTSLine);
- xJack.SetLineOnHook(OpalIxJDevice::PSTNLine);
- xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, FALSE);
- xJack.DisableAudio(OpalIxJDevice::PSTNLine);
- if (speakerphoneSwitch) {
- OutputStatus(IDS_ONSPEAKER);
- speakerphoneSwitch = FALSE;
- }
- else
- HangupCmd();
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SpeedDialSelectDlg::OnCancel()
- {
- Hide();
- }
- ///////////////////////////////////////////////////////////////////////////////
- OpenPhoneConnection::OpenPhoneConnection(OpenPhoneEndPoint & ep,
- unsigned callReference,
- MainWindow * _mainWindow)
- : H323Connection(ep, callReference),
- myEndpoint(ep),
- mainWindow(_mainWindow)
- {
- h245Tunneling = !ep.noTunneling;
- }
- H323Connection::AnswerCallResponse
- OpenPhoneConnection::OnAnswerCall(const PString & caller,
- const H323SignalPDU & /*setupPDU*/,
- H323SignalPDU & /*connectPDU*/)
- {
- return mainWindow->OnAnswerCall(GetCallToken(), caller) ? AnswerCallNow : AnswerCallPending;
- }
- BOOL OpenPhoneConnection::OnAlerting(const H323SignalPDU &, const PString & user)
- {
- mainWindow->OutputStatus(IDS_RINGING, (const char *)user);
- return TRUE;
- }
- void OpenPhoneConnection::OnSelectLogicalChannels()
- {
- if (fastStartState != FastStartDisabled && myEndpoint.noFastStart)
- return;
- #if ENABLE_TRANSMITTER
- H323Connection::OnSelectLogicalChannels();
- #endif
- }
- BOOL OpenPhoneConnection::OnOpenLogicalChannel(const H245_OpenLogicalChannel & openPDU,
- H245_OpenLogicalChannelAck & ackPDU,
- unsigned & errorCode)
- {
- #if ENABLE_RECEIVER
- return H323Connection::OnOpenLogicalChannel(openPDU, ackPDU, errorCode);
- #else
- return FALSE;
- #endif
- }
- void OpenPhoneConnection::OnUserInputString(const PString & value)
- {
- mainWindow->OutputStatus(IDS_USERINPUT, (const char *)value);
- }
- ///////////////////////////////////////////////////////////////////////////////
- OpenPhoneEndPoint::OpenPhoneEndPoint(MainWindow * _mainWindow)
- : mainWindow(_mainWindow)
- {
- phoneThread = NULL;
- }
- OpenPhoneEndPoint::~OpenPhoneEndPoint()
- {
- CloseQuicknet();
- }
- BOOL OpenPhoneEndPoint::OnIncomingCall(H323Connection & connection,
- const H323SignalPDU &,
- H323SignalPDU &)
- {
- PTime now;
- PString nowStr = now.AsString("w h:m a");
- if (!alwaysForwardParty) {
- mainWindow->OutputStatus(IDS_FORWARDING, (const char *)alwaysForwardParty, (const char *)nowStr);
- return !connection.ForwardCall(alwaysForwardParty);
- }
- if (mainWindow->GetCallMode() == MainWindow::IdleCallMode)
- return TRUE;
- if (busyForwardParty.IsEmpty()) {
- mainWindow->OutputStatus(IDS_IGNORINGCALL, (const char *)connection.GetRemotePartyName());
- return FALSE;
- }
- mainWindow->OutputStatus(IDS_FORWARDING, (const char *)busyForwardParty, (const char *)nowStr);
- return !connection.ForwardCall(busyForwardParty);
- }
- BOOL OpenPhoneEndPoint::OnConnectionForwarded(H323Connection & /*connection*/,
- const PString & forwardParty,
- const H323SignalPDU & /*pdu*/)
- {
- return mainWindow->OnConnectionForwarded(forwardParty);
- }
- void OpenPhoneEndPoint::OnConnectionEstablished(H323Connection & connection,
- const PString & token)
- {
- xJack.StopTone(OpalIxJDevice::POTSLine);
- mainWindow->OnConnectionEstablished(token, connection.GetRemotePartyName());
- }
- void OpenPhoneEndPoint::OnConnectionCleared(H323Connection & connection, const PString &)
- {
- xJack.RingLine(OpalIxJDevice::POTSLine, 0);
- mainWindow->OnConnectionCleared(connection);
- if (xJack.IsLineOffHook(OpalIxJDevice::POTSLine))
- xJack.PlayTone(OpalIxJDevice::POTSLine, OpalLineInterfaceDevice::BusyTone);
- else
- xJack.StopTone(OpalIxJDevice::POTSLine);
- }
- H323Connection * OpenPhoneEndPoint::CreateConnection(unsigned callReference)
- {
- return new OpenPhoneConnection(*this, callReference, mainWindow);
- }
- BOOL OpenPhoneEndPoint::OpenAudioChannel(H323Connection & connection,
- BOOL isEncoding,
- unsigned bufferSize,
- H323AudioCodec & codec)
- {
- codec.SetSilenceDetectionMode(silenceDetect ? H323AudioCodec::AdaptiveSilenceDetection
- : H323AudioCodec::NoSilenceDetection);
- if (xJack.IsOpen()) {
- PTRACE(2, "xJacktAttaching channel to codec");
- return codec.AttachChannel(new OpalLineChannel(xJack, OpalIxJDevice::POTSLine, isEncoding));
- }
- return H323EndPoint::OpenAudioChannel(connection, isEncoding, bufferSize, codec);
- }
- BOOL OpenPhoneEndPoint::OpenVideoDevice(H323Connection & connection,
- BOOL isEncoding,
- H323VideoCodec & codec)
- {
- H323VideoDevice * channel = new VideoDevice(mainWindow, isEncoding,
- isEncoding ? GetLocalUserName() : connection.GetRemotePartyName());
- if (isEncoding) {
- PConfig config;
- codec.SetVideoInput(config.GetInteger(VideoSourceConfigKey, 1));
- codec.SetVideoFormat(config.GetInteger(VideoFormatConfigKey, 1) != 0);
- channel->SetSize(352>>(3-videoSize), 288>>(3-videoSize));
- }
- return codec.AttachDevice(channel);
- }
- BOOL OpenPhoneEndPoint::OnStartLogicalChannel(H323Connection &, H323Channel & channel)
- {
- mainWindow->OnLogicalChannel(channel, IDS_STARTCHANNELTX, IDS_STARTCHANNELRX);
- return TRUE;
- }
- void OpenPhoneEndPoint::OnClosedLogicalChannel(H323Connection &, const H323Channel & channel)
- {
- mainWindow->OnLogicalChannel(channel, IDS_STOPCHANNELTX, IDS_STOPCHANNELRX);
- }
- static void UpdateField(PStaticText * field, DWORD value)
- {
- field->SetName(psprintf("%u", value));
- }
- void OpenPhoneEndPoint::OnRTPStatistics(const H323Connection & connection,
- const RTP_Session & session) const
- {
- StatisticsDlg & dlg = *mainWindow->statisticsDialog;
- UpdateField(dlg.packetsSent, session.GetPacketsSent());
- UpdateField(dlg.octetsSent, session.GetOctetsSent());
- UpdateField(dlg.packetsReceived, session.GetPacketsReceived());
- UpdateField(dlg.octetsReceived, session.GetOctetsReceived());
- UpdateField(dlg.packetsLost, session.GetPacketsLost());
- UpdateField(dlg.packetsTooLate, session.GetPacketsTooLate());
- UpdateField(dlg.packetsOutOfOrder, session.GetPacketsOutOfOrder());
- UpdateField(dlg.averageSendTime, session.GetAverageSendTime());
- UpdateField(dlg.maximumSendTime, session.GetMaximumSendTime());
- UpdateField(dlg.minimumSendTime, session.GetMinimumSendTime());
- UpdateField(dlg.averageReceiveTime, session.GetAverageReceiveTime());
- UpdateField(dlg.maximumReceiveTime, session.GetMaximumReceiveTime());
- UpdateField(dlg.minimumReceiveTime, session.GetMinimumReceiveTime());
- UpdateField(dlg.roundTripDelay, connection.GetRoundTripDelay().GetInterval());
- PStringStream duration;
- duration << setprecision(0) << setw(5)
- << (PTime() - connection.GetConnectionStartTime());
- dlg.callDuration->SetName(duration);
- }
- BOOL OpenPhoneEndPoint::Initialise(PConfig & config)
- {
- SetLocalUserName(config.GetString(UsernameConfigKey, GetLocalUserName()));
- PINDEX i = 0;
- PString alias;
- while (!(alias = config.GetString(psprintf(AliasConfigKey, i++))))
- AddAliasName(alias);
- SetInitialBandwidth((unsigned)(config.GetReal(BandwidthConfigKey, 10000)*20));
- SetMaxAudioDelayJitter(config.GetInteger(JitterConfigKey,
- GetInitialBandwidth() < 10000 ? 120 : 50));
- SetRtpIpTypeofService(config.GetInteger(IpTosConfigKey, GetRtpIpTypeofService()));
- noFastStart = config.GetBoolean(NoFastStartConfigKey, FALSE);
- noTunneling = config.GetBoolean(NoTunnelingConfigKey, FALSE);
- silenceDetect = config.GetBoolean(SilenceDetectConfigKey, TRUE);
- alwaysForwardParty = config.GetString(AlwaysForwardPartyConfigKey);
- busyForwardParty = config.GetString(BusyForwardPartyConfigKey);
- videoSize = config.GetInteger(VideoSizeConfigKey, 1);
- autoStartTransmitVideo = videoSize > 1;
- autoStartReceiveVideo = config.GetBoolean(AutoReceiveVideoConfigKey, TRUE);
- // set record and play devices
- SetSoundChannelPlayDevice (config.GetString(SoundPlayConfigKey, GetSoundChannelPlayDevice()));
- SetSoundChannelRecordDevice(config.GetString(SoundRecordConfigKey, GetSoundChannelRecordDevice()));
- SetSoundChannelBufferDepth(config.GetInteger(SoundBuffersConfigKey, GetSoundChannelBufferDepth()));
- OpenQuicknet(config);
- LoadCapabilities(config);
- // start the H323 stack listening for incoming calls
- H323ListenerTCP * listener = new H323ListenerTCP(*this);
- if (StartListener(listener))
- return FindGatekeeper(config);
- PSimpleDialog::Error(mainWindow, IDS_NOPORT, listener->GetListenerPort());
- return FALSE;
- }
- BOOL OpenPhoneEndPoint::OpenQuicknet(PConfig & config)
- {
- PStringArray devices = OpalIxJDevice::GetDeviceNames();
- if (!config.GetBoolean(UseQuicknetConfigKey, devices.GetSize() > 0))
- return FALSE;
- PString device = config.GetString(QuicknetDeviceConfigKey, devices[0]);
- if (xJack.GetName() == device)
- return TRUE;
- InitialiseQuicknetDlg dlg(mainWindow);
- dlg.SetPosition(0, 0, PInteractor::CentreParent, PInteractor::CentreParent);
- dlg.ShowAll();
- dlg.Update();
- CloseQuicknet();
- if (!xJack.Open(device)) {
- PSimpleDialog::Error(mainWindow, IDS_XJACKOPENFAIL, (const char *)device);
- return FALSE;
- }
- xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, FALSE);
- xJack.IsLinePresent(OpalIxJDevice::PSTNLine);
- xJack.DisableAudio(OpalIxJDevice::POTSLine);
- xJack.SetAEC(OpalIxJDevice::POTSLine,
- (OpalIxJDevice::AECLevels)config.GetInteger(AECConfigKey, OpalIxJDevice::AECMedium));
- phoneThread = new QuicknetThread(mainWindow, xJack);
- return TRUE;
- }
- void OpenPhoneEndPoint::CloseQuicknet()
- {
- xJack.Close();
- if (phoneThread != NULL) {
- phoneThread->WaitForTermination();
- delete phoneThread;
- phoneThread = NULL;
- }
- }
- BOOL OpenPhoneEndPoint::FindGatekeeper(PConfig & config)
- {
- if (GetGatekeeper() != NULL)
- mainWindow->OutputStatus(IDS_UNREGGK, (const char *)GetGatekeeper()->GetName());
- if (!config.GetBoolean(UseGatekeeperConfigKey, FALSE)) {
- RemoveGatekeeper();
- return TRUE;
- }
- PString host = config.GetString(GatekeeperHostConfigKey);
- DiscoverGatekeeperDlg dlg(mainWindow);
- dlg.SetPosition(0, 0, PInteractor::CentreParent, PInteractor::CentreParent);
- dlg.ShowAll();
- dlg.Update();
- BOOL found;
- if (host.IsEmpty())
- found = DiscoverGatekeeper();
- else
- found = SetGatekeeper(host);
- if (found) {
- mainWindow->OutputStatus(IDS_USINGGK, (const char *)GetGatekeeper()->GetName());
- return TRUE;
- }
- if (!config.GetBoolean(RequireGatekeeperConfigKey, FALSE))
- return TRUE;
- PSimpleDialog::Error(mainWindow, IDS_NOGATEKEEPER);
- return FALSE;
- }
- void OpenPhoneEndPoint::LoadCapabilities(PConfig & config)
- {
- PINDEX i;
- capabilities.RemoveAll();
- // Add all the codecs we know about
- if (xJack.IsOpen())
- H323_LIDCapability::AddAllCapabilities(xJack, capabilities, 0, 0);
- #ifdef WIN32
- H323_ACMG7231Capability * acmG7231 = new H323_ACMG7231Capability();
- if (acmG7231->IsValid())
- SetCapability(0, 0, acmG7231);
- else
- delete acmG7231;
- #endif
- SetCapability(0, 0, new H323_LPC10Capability(*this));
- SetCapability(0, 0, new H323_GSM0610Capability);
- SetCapability(0, 0, new H323_G711Capability(H323_G711Capability::muLaw));
- SetCapability(0, 0, new H323_G711Capability(H323_G711Capability::ALaw));
- // Now get all of the codec names we have remembered in PConfig
- PStringArray enabledCodecs;
- PStringArray disabledCodecs;
- PINDEX codecNum = 0;
- for (;;) {
- PString key = psprintf(CodecsConfigKey, ++codecNum);
- PString name = config.GetString(CodecsConfigSection, key, "");
- if (name.IsEmpty())
- break;
- BOOL needRewrite = FALSE;
- PINDEX suffixPos = name.Find(OffCodecSuffix);
- if (suffixPos != P_MAX_INDEX)
- disabledCodecs[disabledCodecs.GetSize()] = name(0, suffixPos-1);
- else {
- PString enabledCodecName;
- suffixPos = name.Find(OnCodecSuffix);
- if (suffixPos != P_MAX_INDEX)
- enabledCodecName = name.Left(suffixPos);
- else {
- // Compatibility with old entries, remove the <num> and add (On).
- if (name[name.GetLength()-1] == '>') {
- PINDEX pos = name.FindLast('<');
- if (name[pos-1] == ' ')
- pos--;
- name.Delete(pos, P_MAX_INDEX);
- name += OnCodecSuffix;
- needRewrite = TRUE;
- }
- }
- enabledCodecs[enabledCodecs.GetSize()] = enabledCodecName;
- }
- // See if codec is physically available, disable if not
- BOOL notPhysical = TRUE;
- for (i = 0; i < capabilities.GetSize(); i++) {
- if (name.Find(capabilities[i].GetFormatName()) == 0) {
- notPhysical = FALSE;
- unsigned txFrames = 0;
- PINDEX left = name.FindLast('[');
- PINDEX right = name.FindLast(']');
- if (left != P_MAX_INDEX && right != P_MAX_INDEX)
- txFrames = name(left+1, right-1).AsUnsigned();
- if (txFrames > 0 && txFrames < 100)
- capabilities[i].SetTxFramesInPacket(txFrames);
- else {
- name.sprintf(" [%u]", capabilities[i].GetTxFramesInPacket());
- needRewrite = TRUE;
- }
- break;
- }
- }
- if (notPhysical) {
- name.Replace(OnCodecSuffix, OffCodecSuffix);
- needRewrite = TRUE;
- }
- if (needRewrite)
- config.SetString(CodecsConfigSection, key, name);
- }
- // Remove all of the disabled codecs
- for (i = 0; i < disabledCodecs.GetSize(); i++)
- capabilities.Remove(disabledCodecs[i]);
- // Now go through the list of real codecs and add missing entries to PConfig
- for (i = 0; i < capabilities.GetSize(); i++) {
- PString realCodec = capabilities[i].GetFormatName();
- if (enabledCodecs.GetValuesIndex(realCodec) == P_MAX_INDEX)
- config.SetString(CodecsConfigSection,
- psprintf(CodecsConfigKey, codecNum++),
- psprintf("%s%s [%u]",
- (const char *)realCodec,
- OnCodecSuffix,
- capabilities[i].GetTxFramesInPacket()));
- }
- // Reorder the codecs we have
- capabilities.Reorder(enabledCodecs);
- unsigned qcif = config.GetBoolean(H261QCIFConfigKey, TRUE) ? 1 : 0;
- unsigned cif = config.GetBoolean(H261CIFConfigKey, TRUE) ? 2 : 0;
- if (qcif > 0 || cif > 0)
- SetCapability(0, P_MAX_INDEX, new H323_H261Capability(qcif, cif));
- SetCapability(0, P_MAX_INDEX, new H323_UserInputCapability);
- //SetCapability(0, P_MAX_INDEX, new H323_T120Capability);
- PTRACE(1, "CodectCapability Table:n" << setprecision(4) << capabilities);
- }
- ///////////////////////////////////////////////////////////////////////////////
- QuicknetThread::QuicknetThread(MainWindow * wnd, OpalIxJDevice & jack)
- : PThread(10000, NoAutoDeleteThread),
- mainWindow(wnd),
- xJack(jack)
- {
- Resume();
- }
- void QuicknetThread::Main()
- {
- PTRACE(3, "xJacktStarted hook monitor thread");
- while (xJack.IsOpen()) {
- switch (mainWindow->GetCallMode()) {
- case MainWindow::IdleCallMode :
- if (xJack.IsLineRinging(OpalIxJDevice::PSTNLine)) {
- PString callerID;
- if (xJack.GetCallerID(OpalIxJDevice::PSTNLine, callerID))
- mainWindow->OutputStatus(IDS_CALLERID, (const char *)callerID);
- else
- mainWindow->OutputStatus(IDS_LINERINGING);
- mainWindow->SetCallMode(MainWindow::IncomingLineCall);
- xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, TRUE);
- }
- break;
- case MainWindow::IncomingLineCall :
- if (!xJack.IsLineRinging(OpalIxJDevice::PSTNLine)) {
- xJack.SetLineToLineDirect(OpalIxJDevice::POTSLine, OpalIxJDevice::PSTNLine, FALSE);
- mainWindow->OutputStatus(IDS_CALLDISAPPEARED);
- mainWindow->SetCallMode(MainWindow::IdleCallMode);
- }
- break;
- case MainWindow::ApplicationShuttingDown :
- return;
- default :
- break;
- }
- if (xJack.IsLineOffHook(OpalIxJDevice::POTSLine)) {
- PTRACE(3, "xJacktHandset lifted");
- mainWindow->OnHandsetLifted(xJack);
- while (xJack.IsLineOffHook(OpalIxJDevice::POTSLine))
- PThread::Current()->Sleep(500);
- mainWindow->OnHandsetReturned(xJack);
- PTRACE(3, "xJacktRestarted hook monitor thread");
- }
- Sleep(100);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- VideoWindow::VideoWindow(PInteractor * parent, VideoDevice * dev, BOOL local)
- : PFloatingDialog(parent)
- {
- device = dev;
- localVideo = local;
- canvas = NULL;
- }
- VideoWindow::~VideoWindow()
- {
- // Release the mutex and request it again, this guarantees that if the video
- // thread happens to be in the mutex wait in WriteLineSegment() it is executed
- // and exited from that function before continuing out of the shutdown procedure.
- mutex.Wait();
- delete canvas;
- }
- void VideoWindow::OnClose()
- {
- Shutdown();
- PConfig config;
- PPoint pos = GetPosition(PixelCoords);
- config.SetInteger(localVideo ? LocalVideoWindowLeftConfigKey
- : RemoteVideoWindowLeftConfigKey, pos.X());
- config.SetInteger(localVideo ? LocalVideoWindowTopConfigKey
- : RemoteVideoWindowTopConfigKey, pos.Y());
- PFloatingDialog::OnClose();
- }
- void VideoWindow::OnCancel()
- {
- Shutdown();
- Close();
- }
- void VideoWindow::OnRedraw(PCanvas & redrawCanvas)
- {
- if (!image.IsNULL())
- redrawCanvas.DrawPixels(0, 0, image);
- // We create canvas in here as under Win32 we must have the construction AND
- // destruction of a canvas in the "GUI" thread.
- if (canvas == NULL) {
- canvas = new PDrawCanvas(this);
- canvas->SetViewportRect(canvas->GetMappingRect());
- }
- }
- void VideoWindow::SetVideoSize(int width, int height)
- {
- SetDimensions(width, height, PixelCoords);
- if (image.IsNULL()) {
- image = PPixelImage(width, height, 24);
- raster = PPixelImage(width, 1, 24);
- }
- PConfig config;
- PORDINATE x = config.GetInteger(localVideo ? LocalVideoWindowLeftConfigKey
- : RemoteVideoWindowLeftConfigKey,
- localVideo ? 0 : 300);
- PORDINATE y = config.GetInteger(localVideo ? LocalVideoWindowTopConfigKey
- : RemoteVideoWindowTopConfigKey,
- GetParent()->GetDimensions(PixelCoords).Height());
- SetPosition(x, y, TopLeftPixels, TopLeftPixels);
- Show();
- }
- BOOL VideoWindow::WriteLineSegment(int x, int y, unsigned len, const BYTE * data)
- {
- PWaitAndSignal wait(mutex);
- if (device == NULL || image.IsNULL())
- return FALSE;
- memcpy(image->GetRasterDataPtr(y)+x*3, data, len*3);
- if (canvas == NULL)
- Invalidate();
- else {
- memcpy(raster->GetRasterDataPtr(0), image->GetRasterDataPtr(y), image->GetDimensions().Width()*3);
- canvas->DrawPixels(0, y, raster);
- }
- return TRUE;
- }
- void VideoWindow::Shutdown()
- {
- mutex.Wait();
- if (device != NULL) {
- device->windowOpen = FALSE;
- device = NULL;
- }
- mutex.Signal();
- }
- ///////////////////////////////////////////////////////////////////////////////
- VideoDevice::VideoDevice(MainWindow * mainWindow, BOOL local, const PString & title)
- {
- window = new VideoWindow(mainWindow, this, local);
- window->SetTitle(title);
- windowOpen = TRUE;
- rgbReverseOrder = TRUE;
- }
- VideoDevice::~VideoDevice()
- {
- if (windowOpen)
- window->OnCancel();
- }
- void VideoDevice::SetSize(int w, int h)
- {
- H323VideoDevice::SetSize(w, h);
- if (windowOpen)
- window->SetVideoSize(width, height);
- }
- BOOL VideoDevice::WriteLineSegment(int x, int y, unsigned len, const BYTE * data)
- {
- if (windowOpen)
- return window->WriteLineSegment(x, y, len, data);
- return FALSE;
- }
- // End of File ///////////////////////////////////////////////////////////////