OPAL Version 3.10.4

- Main Page
- Related Pages
- Namespaces
- Data Structures
- Files

- File List
- Globals

manager.h
Go to the documentation of this file.
1 /*
2 * manager.h
3 *
4 * OPAL system manager.
5 *
6 * Open Phone Abstraction Library (OPAL)
7 * Formally known as the Open H323 project.
8 *
9 * Copyright (c) 2001 Equivalence Pty. Ltd.
10 *
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/
15 *
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
19 * under the License.
20 *
21 * The Original Code is Open Phone Abstraction Library.
22 *
23 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 *
25 * Contributor(s): ______________________________________.
26 *
27 * $Revision: 26937 $
28 * $Author: rjongbloed $
29 * $Date: 2012-02-06 19:54:19 -0600 (Mon, 06 Feb 2012) $
30 */
31
32 #ifndef OPAL_OPAL_MANAGER_H
33 #define OPAL_OPAL_MANAGER_H
34
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38
39 #include <opal/buildopts.h>
40
41 #include <opal/pres_ent.h>
42 #include <opal/call.h>
43 #include <opal/connection.h> //OpalConnection::AnswerCallResponse
44 #include <opal/guid.h>
45 #include <codec/silencedetect.h>
46 #include <codec/echocancel.h>
47 #include <ptclib/pstun.h>
48 #include <ptclib/url.h>
49
50 #if OPAL_VIDEO
51 #include <ptlib/videoio.h>
52 #endif
53
54 class OpalEndPoint;
55 class OpalMediaPatch;
56
57
74 class OpalManager : public PObject
75 {
76 PCLASSINFO(OpalManager, PObject);
77 public:
82 OpalManager();
83
88 ~OpalManager();
90
100 void AttachEndPoint(
101 OpalEndPoint * endpoint,
102 const PString & prefix = PString::Empty()
103 );
104
108 void DetachEndPoint(
109 const PString & prefix
110 );
111 void DetachEndPoint(
112 OpalEndPoint * endpoint
113 );
114
117 OpalEndPoint * FindEndPoint(
118 const PString & prefix
119 );
120
123 PList<OpalEndPoint> GetEndPoints() const;
124
130 void ShutDownEndpoints();
132
151 virtual PSafePtr<OpalCall> SetUpCall(
152 const PString & partyA,
153 const PString & partyB,
154 void * userData = NULL,
155 unsigned options = 0,
156 OpalConnection::StringOptions * stringOptions = NULL
157 );
158 virtual PBoolean SetUpCall(
159 const PString & partyA,
160 const PString & partyB,
161 PString & token,
162 void * userData = NULL,
163 unsigned options = 0,
164 OpalConnection::StringOptions * stringOptions = NULL
165 );
166
172 virtual PBoolean HasCall(
173 const PString & token
174 ) { return activeCalls.FindWithLock(token, PSafeReference) != NULL; }
175
178 PINDEX GetCallCount() const { return activeCalls.GetSize(); }
179
182 PArray<PString> GetAllCalls() const { return activeCalls.GetKeys(); }
183
192 PSafePtr<OpalCall> FindCallWithLock(
193 const PString & token,
194 PSafetyMode mode = PSafeReadWrite
195 ) { return activeCalls.FindWithLock(token, mode); }
196
205 virtual void OnEstablishedCall(
206 OpalCall & call
207 );
208
215 virtual PBoolean IsCallEstablished(
216 const PString & token
217 );
218
226 virtual PBoolean ClearCall(
227 const PString & token,
228 OpalConnection::CallEndReason reason = OpalConnection::EndedByLocalUser,
229 PSyncPoint * sync = NULL
230 );
231
239 virtual PBoolean ClearCallSynchronous(
240 const PString & token,
241 OpalConnection::CallEndReason reason = OpalConnection::EndedByLocalUser
242 );
243
249 virtual void ClearAllCalls(
250 OpalConnection::CallEndReason reason = OpalConnection::EndedByLocalUser,
251 PBoolean wait = true
252 );
253
267 virtual void OnClearedCall(
268 OpalCall & call
269 );
270
279 virtual OpalCall * CreateCall(
280 void * userData
281 );
282 OpalCall * InternalCreateCall();
283
292 virtual void DestroyCall(
293 OpalCall * call
294 );
295
300 virtual PString GetNextToken(char prefix);
302
311 virtual PSafePtr<OpalPresentity> AddPresentity(
312 const PString & presentity
313 );
314
317 virtual PSafePtr<OpalPresentity> GetPresentity(
318 const PString & presentity,
319 PSafetyMode mode = PSafeReference
320 );
321
324 virtual PStringList GetPresentities() const;
325
328 virtual bool RemovePresentity(
329 const PString & presentity
330 );
332
337 virtual PBoolean Message(
338 const PString & to,
339 const PString & body
340 );
341 virtual PBoolean Message(
342 const PURL & to,
343 const PString & type,
344 const PString & body,
345 PURL & from,
346 PString & conversationId
347 );
348 virtual PBoolean Message(
349 OpalIM & message
350 );
351
354 virtual void OnMessageReceived(
355 const OpalIM & message
356 );
357
359
396 virtual PSafePtr<OpalConnection> MakeConnection(
397 OpalCall & call,
398 const PString & party,
399 void * userData = NULL,
400 unsigned int options = 0,
401 OpalConnection::StringOptions * stringOptions = NULL
402 );
403
409 virtual void OnNewConnection(
410 OpalConnection & connection
411 );
412
439 virtual PBoolean OnIncomingConnection(
440 OpalConnection & connection,
441 unsigned options,
442 OpalConnection::StringOptions * stringOptions
443 );
444
451 virtual bool OnRouteConnection(
452 PStringSet & routesTried,
453 const PString & a_party,
454 const PString & b_party,
455 OpalCall & call,
456 unsigned options,
457 OpalConnection::StringOptions * stringOptions
458 );
459
475 virtual void OnProceeding(
476 OpalConnection & connection
477 );
478
495 virtual void OnAlerting(
496 OpalConnection & connection
497 );
498
515 virtual OpalConnection::AnswerCallResponse OnAnswerCall(
516 OpalConnection & connection,
517 const PString & caller
518 );
519
531 virtual void OnConnected(
532 OpalConnection & connection
533 );
534
548 virtual void OnEstablished(
549 OpalConnection & connection
550 );
551
567 virtual void OnReleased(
568 OpalConnection & connection
569 );
570
577 virtual void OnHold(
578 OpalConnection & connection,
579 bool fromRemote,
580 bool onHold
581 );
582 virtual void OnHold(OpalConnection & connection); // For backward compatibility
583
588 virtual PBoolean OnForwarded(
589 OpalConnection & connection,
590 const PString & remoteParty
591 );
592
638 virtual bool OnTransferNotify(
639 OpalConnection & connection,
640 const PStringToString & info
641 );
643
644
654 virtual OpalMediaFormatList GetCommonMediaFormats(
655 bool transportable,
656 bool pcmAudio
657 ) const;
658
668 virtual void AdjustMediaFormats(
669 bool local,
670 const OpalConnection & connection,
671 OpalMediaFormatList & mediaFormats
672 ) const;
673
676 virtual PBoolean IsMediaBypassPossible(
677 const OpalConnection & source,
678 const OpalConnection & destination,
679 unsigned sessionID
680 ) const;
681
697 virtual PBoolean OnOpenMediaStream(
698 OpalConnection & connection,
699 OpalMediaStream & stream
700 );
701
710 virtual RTP_UDP * CreateRTPSession (const RTP_Session::Params & params);
711
719 virtual void OnRTPStatistics(
720 const OpalConnection & connection,
721 const RTP_Session & session
722 );
723
740 virtual bool OnLocalRTP(
741 OpalConnection & connection1,
742 OpalConnection & connection2,
743 unsigned sessionID,
744 bool opened
745 ) const;
746
772 bool SetMediaPassThrough(
773 const PString & token1,
774 const PString & token2,
775 bool bypass,
776 unsigned sessionID = 0,
777 bool network = true
778 );
779 static bool SetMediaPassThrough(
780 OpalConnection & connection1,
781 OpalConnection & connection2,
782 bool bypass,
783 unsigned sessionID = 0
784 );
785
790 virtual void OnClosedMediaStream(
791 const OpalMediaStream & stream
792 );
793
794 #if OPAL_VIDEO
795
797 virtual PBoolean CreateVideoInputDevice(
798 const OpalConnection & connection,
799 const OpalMediaFormat & mediaFormat,
800 PVideoInputDevice * & device,
801 PBoolean & autoDelete
802 );
803
807 virtual PBoolean CreateVideoOutputDevice(
808 const OpalConnection & connection,
809 const OpalMediaFormat & mediaFormat,
810 PBoolean preview,
811 PVideoOutputDevice * & device,
812 PBoolean & autoDelete
813 );
814 #endif
815
823 virtual OpalMediaPatch * CreateMediaPatch(
824 OpalMediaStream & source,
825 PBoolean requiresPatchThread = true
826 );
827
832 virtual void DestroyMediaPatch(
833 OpalMediaPatch * patch
834 );
835
842 virtual void OnStartMediaPatch(
843 OpalConnection & connection,
844 OpalMediaPatch & patch
845 );
846
849 virtual void OnStopMediaPatch(
850 OpalConnection & connection,
851 OpalMediaPatch & patch
852 );
854
862 virtual void OnUserInputString(
863 OpalConnection & connection,
864 const PString & value
865 );
866
873 virtual void OnUserInputTone(
874 OpalConnection & connection,
875 char tone,
876 int duration
877 );
878
881 virtual PString ReadUserInput(
882 OpalConnection & connection,
883 const char * terminators = "#\r\n",
884 unsigned lastDigitTimeout = 4,
885 unsigned firstDigitTimeout = 30
886 );
888
891
892 enum MessageWaitingType {
893 NoMessageWaiting,
894 VoiceMessageWaiting,
895 FaxMessageWaiting,
896 PagerMessageWaiting,
897 MultimediaMessageWaiting,
898 TextMessageWaiting,
899 NumMessageWaitingTypes
900 };
901
912 virtual void OnMWIReceived(
913 const PString & party,
914 MessageWaitingType type,
915 const PString & extraInfo
916 );
917
918
919 class RouteEntry : public PObject
920 {
921 PCLASSINFO(RouteEntry, PObject);
922 public:
923 RouteEntry(const PString & pat, const PString & dest);
924 void PrintOn(ostream & strm) const;
925 PString pattern;
926 PString destination;
927 PRegularExpression regex;
928 };
929 PARRAY(RouteTable, RouteEntry);
930
1041 virtual PBoolean AddRouteEntry(
1042 const PString & spec
1043 );
1044
1051 PBoolean SetRouteTable(
1052 const PStringArray & specs
1053 );
1054
1059 void SetRouteTable(
1060 const RouteTable & table
1061 );
1062
1065 const RouteTable & GetRouteTable() const { return m_routeTable; }
1066
1074 virtual PString ApplyRouteTable(
1075 const PString & source,
1076 const PString & destination,
1077 PINDEX & entry
1078 );
1080
1081 #if OPAL_HAS_MIXER
1082
1092 virtual PBoolean StartRecording(
1093 const PString & callToken,
1094 const PFilePath & filename,
1095 const OpalRecordManager::Options & options = false
1096 );
1097
1100 virtual bool IsRecording(
1101 const PString & callToken
1102 );
1103
1108 virtual bool StopRecording(
1109 const PString & callToken
1110 );
1111
1113 #endif
1114
1119 const OpalProductInfo & GetProductInfo() const { return productInfo; }
1120
1123 void SetProductInfo(
1124 const OpalProductInfo & info,
1125 bool updateAll = true
1126 );
1127
1130 const PString & GetDefaultUserName() const { return defaultUserName; }
1131
1134 void SetDefaultUserName(
1135 const PString & name,
1136 bool updateAll = true
1137 );
1138
1141 const PString & GetDefaultDisplayName() const { return defaultDisplayName; }
1142
1145 void SetDefaultDisplayName(
1146 const PString & name,
1147 bool updateAll = true
1148 );
1149
1150 #if OPAL_VIDEO
1151
1152 //
1153 // these functions are deprecated and used only for backwards compatibility
1154 // applications should use OpalConnection::GetAutoStart() to check whether
1155 // a specific media type can be auto-started
1156 //
1157
1160 bool CanAutoStartReceiveVideo() const { return (OpalMediaType::Video().GetAutoStart()&OpalMediaType::Receive) != 0; }
1161
1164 void SetAutoStartReceiveVideo(bool can) { OpalMediaType::Video().GetDefinition()->SetAutoStart(OpalMediaType::Receive, can); }
1165
1168 bool CanAutoStartTransmitVideo() const { return (OpalMediaType::Video().GetAutoStart()&OpalMediaType::Transmit) != 0; }
1169
1172 void SetAutoStartTransmitVideo(bool can) { OpalMediaType::Video().GetDefinition()->SetAutoStart(OpalMediaType::Transmit, can); }
1173
1174 #endif
1175
1182 virtual PBoolean IsLocalAddress(
1183 const PIPSocket::Address & remoteAddress
1184 ) const;
1185
1203 virtual PBoolean IsRTPNATEnabled(
1204 OpalConnection & connection,
1205 const PIPSocket::Address & localAddr,
1206 const PIPSocket::Address & peerAddr,
1207 const PIPSocket::Address & signalAddr,
1208 PBoolean incoming
1209 );
1210
1217 virtual PBoolean TranslateIPAddress(
1218 PIPSocket::Address & localAddress,
1219 const PIPSocket::Address & remoteAddress
1220 );
1221
1224 const PString & GetTranslationHost() const { return translationHost; }
1225
1228 bool SetTranslationHost(
1229 const PString & host
1230 );
1231
1234 const PIPSocket::Address & GetTranslationAddress() const { return translationAddress; }
1235
1238 void SetTranslationAddress(
1239 const PIPSocket::Address & address
1240 );
1241
1247 virtual PNatMethod * GetNatMethod(
1248 const PIPSocket::Address & remoteAddress = PIPSocket::GetDefaultIpAny()
1249 ) const;
1250
1255 PSTUNClient::NatTypes SetSTUNServer(
1256 const PString & server
1257 );
1258
1261 const PString & GetSTUNServer() const { return stunServer; }
1262
1265 PSTUNClient * GetSTUNClient() const { return stun; }
1266
1269 WORD GetTCPPortBase() const { return tcpPorts.base; }
1270
1273 WORD GetTCPPortMax() const { return tcpPorts.max; }
1274
1277 void SetTCPPorts(unsigned tcpBase, unsigned tcpMax);
1278
1281 WORD GetNextTCPPort();
1282
1285 WORD GetUDPPortBase() const { return udpPorts.base; }
1286
1289 WORD GetUDPPortMax() const { return udpPorts.max; }
1290
1293 void SetUDPPorts(unsigned udpBase, unsigned udpMax);
1294
1297 WORD GetNextUDPPort();
1298
1301 WORD GetRtpIpPortBase() const { return rtpIpPorts.base; }
1302
1305 WORD GetRtpIpPortMax() const { return rtpIpPorts.max; }
1306
1309 void SetRtpIpPorts(unsigned udpBase, unsigned udpMax);
1310
1313 WORD GetRtpIpPortPair();
1314
1317 BYTE GetMediaTypeOfService() const { return m_defaultMediaTypeOfService; }
1318
1321 void SetMediaTypeOfService(unsigned tos) { m_defaultMediaTypeOfService = (BYTE)tos; }
1322
1323 // For backward compatibility
1324 BYTE P_DEPRECATED GetRtpIpTypeofService() const { return m_defaultMediaTypeOfService; }
1325 void P_DEPRECATED SetRtpIpTypeofService(unsigned tos) { m_defaultMediaTypeOfService = (BYTE)tos; }
1326
1329 BYTE GetMediaTypeOfService(const OpalMediaType & type) const;
1330
1333 void SetMediaTypeOfService(const OpalMediaType & type, unsigned tos);
1334
1339 PINDEX GetMaxRtpPayloadSize() const { return rtpPayloadSizeMax; }
1340
1345 void SetMaxRtpPayloadSize(
1346 PINDEX size,
1347 bool mtu = false
1348 ) { rtpPayloadSizeMax = size - (mtu ? (20+16+12) : 0); }
1349
1353 PINDEX GetMaxRtpPacketSize() const { return rtpPacketSizeMax; }
1354
1358 void SetMaxRtpPacketSize(
1359 PINDEX size
1360 ) { rtpPacketSizeMax = size; }
1361
1365 unsigned GetMinAudioJitterDelay() const { return minAudioJitterDelay; }
1366
1370 unsigned GetMaxAudioJitterDelay() const { return maxAudioJitterDelay; }
1371
1381 void SetAudioJitterDelay(
1382 unsigned minDelay,
1383 unsigned maxDelay
1384 );
1385
1388 const PStringArray & GetMediaFormatOrder() const { return mediaFormatOrder; }
1389
1392 void SetMediaFormatOrder(
1393 const PStringArray & order
1394 );
1395
1401 const PStringArray & GetMediaFormatMask() const { return mediaFormatMask; }
1402
1408 void SetMediaFormatMask(
1409 const PStringArray & mask //< New mask
1410 );
1411
1414 virtual void SetSilenceDetectParams(
1415 const OpalSilenceDetector::Params & params
1416 ) { silenceDetectParams = params; }
1417
1420 const OpalSilenceDetector::Params & GetSilenceDetectParams() const { return silenceDetectParams; }
1421
1422 #if OPAL_AEC
1423
1425 virtual void SetEchoCancelParams(
1426 const OpalEchoCanceler::Params & params
1427 ) { echoCancelParams = params; }
1428
1431 const OpalEchoCanceler::Params & GetEchoCancelParams() const { return echoCancelParams; }
1432 #endif
1433
1434 #if OPAL_VIDEO
1435
1443 virtual PBoolean SetVideoInputDevice(
1444 const PVideoDevice::OpenArgs & deviceArgs
1445 );
1446
1450 const PVideoDevice::OpenArgs & GetVideoInputDevice() const { return videoInputDevice; }
1451
1459 virtual PBoolean SetVideoPreviewDevice(
1460 const PVideoDevice::OpenArgs & deviceArgs
1461 );
1462
1466 const PVideoDevice::OpenArgs & GetVideoPreviewDevice() const { return videoPreviewDevice; }
1467
1475 virtual PBoolean SetVideoOutputDevice(
1476 const PVideoDevice::OpenArgs & deviceArgs
1477 );
1478
1482 const PVideoDevice::OpenArgs & GetVideoOutputDevice() const { return videoOutputDevice; }
1483
1484 #endif
1485
1486 PBoolean DetectInBandDTMFDisabled() const
1487 { return disableDetectInBandDTMF; }
1488
1491 void DisableDetectInBandDTMF(
1492 PBoolean mode
1493 ) { disableDetectInBandDTMF = mode; }
1494
1497 const PTimeInterval & GetNoMediaTimeout() const { return noMediaTimeout; }
1498
1501 PBoolean SetNoMediaTimeout(
1502 const PTimeInterval & newInterval
1503 );
1504
1507 const PString & GetDefaultILSServer() const { return ilsServer; }
1508
1511 void SetDefaultILSServer(
1512 const PString & server
1513 ) { ilsServer = server; }
1515
1516 // needs to be public for gcc 3.4
1517 void GarbageCollection();
1518
1519 #ifdef OPAL_ZRTP
1520 virtual bool GetZRTPEnabled() const;
1521 #endif
1522
1523 virtual void OnApplyStringOptions(
1524 OpalConnection & conn,
1525 OpalConnection::StringOptions & stringOptions
1526 );
1527
1528 protected:
1529 // Configuration variables
1530 OpalProductInfo productInfo;
1531
1532 PString defaultUserName;
1533 PString defaultDisplayName;
1534
1535 BYTE m_defaultMediaTypeOfService;
1536 map<OpalMediaType, BYTE> m_mediaTypeOfService;
1537
1538 PINDEX rtpPayloadSizeMax;
1539 PINDEX rtpPacketSizeMax;
1540 unsigned minAudioJitterDelay;
1541 unsigned maxAudioJitterDelay;
1542 PStringArray mediaFormatOrder;
1543 PStringArray mediaFormatMask;
1544 PBoolean disableDetectInBandDTMF;
1545 PTimeInterval noMediaTimeout;
1546 PString ilsServer;
1547
1548 OpalSilenceDetector::Params silenceDetectParams;
1549 #if OPAL_AEC
1550 OpalEchoCanceler::Params echoCancelParams;
1551 #endif
1552
1553 #if OPAL_VIDEO
1554 PVideoDevice::OpenArgs videoInputDevice;
1555 PVideoDevice::OpenArgs videoPreviewDevice;
1556 PVideoDevice::OpenArgs videoOutputDevice;
1557 #endif
1558
1559 struct PortInfo {
1560 void Set(
1561 unsigned base,
1562 unsigned max,
1563 unsigned range,
1564 unsigned dflt
1565 );
1566 WORD GetNext(
1567 unsigned increment
1568 );
1569
1570 PMutex mutex;
1571 WORD base;
1572 WORD max;
1573 WORD current;
1574 } tcpPorts, udpPorts, rtpIpPorts;
1575
1576 class InterfaceMonitor : public PInterfaceMonitorClient
1577 {
1578 PCLASSINFO(InterfaceMonitor, PInterfaceMonitorClient);
1579
1580 enum {
1581 OpalManagerInterfaceMonitorClientPriority = 100,
1582 };
1583 public:
1584 InterfaceMonitor(OpalManager & manager);
1585
1586 protected:
1587 virtual void OnAddInterface(const PIPSocket::InterfaceEntry & entry);
1588 virtual void OnRemoveInterface(const PIPSocket::InterfaceEntry & entry);
1589
1590 OpalManager & m_manager;
1591 };
1592
1593 PString translationHost;
1594 PIPSocket::Address translationAddress;
1595 PString stunServer;
1596 PSTUNClient * stun;
1597 InterfaceMonitor * interfaceMonitor;
1598
1599 RouteTable m_routeTable;
1600 PMutex m_routeMutex;
1601
1602 // Dynamic variables
1603 PReadWriteMutex endpointsMutex;
1604 PList<OpalEndPoint> endpointList;
1605 std::map<PString, OpalEndPoint *> endpointMap;
1606
1607 PAtomicInteger lastCallTokenID;
1608
1609 class CallDict : public PSafeDictionary<PString, OpalCall>
1610 {
1611 public:
1612 CallDict(OpalManager & mgr) : manager(mgr) { }
1613 virtual void DeleteObject(PObject * object) const;
1614 OpalManager & manager;
1615 } activeCalls;
1616
1617 PSafeDictionary<PString, OpalPresentity> m_presentities;
1618
1619 PAtomicInteger m_clearingAllCallsCount;
1620 PMutex m_clearingAllCallsMutex;
1621 PSyncPoint m_allCallsCleared;
1622 void InternalClearAllCalls(OpalConnection::CallEndReason reason, bool wait, bool first);
1623
1624 PThread * garbageCollector;
1625 PSyncPoint garbageCollectExit;
1626 bool garbageCollectSkip;
1627 PDECLARE_NOTIFIER(PThread, OpalManager, GarbageMain);
1628
1629 #ifdef OPAL_ZRTP
1630 bool zrtpEnabled;
1631 #endif
1632
1633 friend OpalCall::OpalCall(OpalManager & mgr);
1634 friend void OpalCall::InternalOnClear();
1635
1636 private:
1637 P_REMOVE_VIRTUAL(OpalCall *,CreateCall(), 0);
1638 P_REMOVE_VIRTUAL(PBoolean, OnIncomingConnection(OpalConnection &, unsigned), false);
1639 P_REMOVE_VIRTUAL(PBoolean, OnIncomingConnection(OpalConnection &), false);
1640 P_REMOVE_VIRTUAL(PBoolean, OnStartMediaPatch(const OpalMediaPatch &), false);
1641 P_REMOVE_VIRTUAL_VOID(AdjustMediaFormats(const OpalConnection &, OpalMediaFormatList &) const);
1642 P_REMOVE_VIRTUAL_VOID(OnMessageReceived(const PURL&,const PString&,const PURL&,const PString&,const PString&,const PString&));
1643
1644
1645 #ifdef OPAL_HAS_IM
1646 public:
1647 OpalIMManager & GetIMManager() { return *m_imManager; }
1648
1649 protected:
1650 OpalIMManager * m_imManager;
1651 #endif
1652 };
1653
1654
1655 PString OpalGetVersion();
1656 unsigned OpalGetMajorVersion();
1657 unsigned OpalGetMinorVersion();
1658 unsigned OpalGetBuildNumber();
1659
1660
1661 #endif // OPAL_OPAL_MANAGER_H
1662
1663
1664 // End of File ///////////////////////////////////////////////////////////////