reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
SipXMediaStackAdapter.cxx
Go to the documentation of this file.
1// sipX includes
2#if (_MSC_VER >= 1600)
3#include <stdint.h> // Use Visual Studio's stdint.h
4#define _MSC_STDINT_H_ // This define will ensure that stdint.h in sipXport tree is not used
5#endif
6#include <sdp/SdpCodec.h>
7#include <os/OsConfigDb.h>
8#include <mp/MpCodecFactory.h>
9#include <mp/MprBridge.h>
10#include <mp/MpResourceFactory.h>
11#include <mp/MpResourceTopology.h>
12#include <mi/CpMediaInterfaceFactoryFactory.h>
13#include <CpTopologyGraphFactoryImpl.h>
14
15// resip includes
16#include <rutil/Log.hxx>
17#include <rutil/Logger.hxx>
18#include <rutil/Lock.hxx>
19#include <rutil/Random.hxx>
25
26#include "ReconSubsystem.hxx"
27#include "UserAgent.hxx"
30#include "SipXConversation.hxx"
31#include "Participant.hxx"
32#include "SipXBridgeMixer.hxx"
33#include "DtmfEvent.hxx"
37#include "Conversation.hxx"
39
40#if defined(WIN32) && !defined(__GNUC__)
41#pragma warning( disable : 4355 )
42#endif
43
44using namespace recon;
45using namespace resip;
46using namespace std;
47
48#ifdef WIN32
49std::string getExecutableDir()
50{
51 char buf[MAX_PATH];
52 memset(buf, 0, sizeof(buf));
53 DWORD len = GetModuleFileNameA(GetModuleHandle(NULL), buf, sizeof(buf) - 1);
54 // Remove executable name
55 for (char* p = buf + len; p > buf; p--) {
56 if (*p == '\\') {
57 *p = 0;
58 break;
59 }
60 }
61 return std::string(buf);
62}
63#endif
64
65#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON
66
70
71SipXMediaStackAdapter::SipXMediaStackAdapter(ConversationManager& conversationManager, bool localAudioEnabled, MediaInterfaceMode mediaInterfaceMode, bool enableExtraPlayAndRecordResources)
72: MediaStackAdapter(conversationManager),
73 mLocalAudioEnabled(localAudioEnabled),
74 mMediaInterfaceMode(mediaInterfaceMode),
75 mEnableExtraPlayAndRecordResources(enableExtraPlayAndRecordResources),
76 mMediaFactory(0),
77 mSipXTOSValue(0)
78{
79 init();
80}
81
82SipXMediaStackAdapter::SipXMediaStackAdapter(ConversationManager& conversationManager, bool localAudioEnabled, MediaInterfaceMode mediaInterfaceMode, int defaultSampleRate, int maxSampleRate, bool enableExtraPlayAndRecordResources)
83: MediaStackAdapter(conversationManager),
84 mLocalAudioEnabled(localAudioEnabled),
85 mMediaInterfaceMode(mediaInterfaceMode),
86 mEnableExtraPlayAndRecordResources(enableExtraPlayAndRecordResources),
87 mMediaFactory(0),
88 mSipXTOSValue(0)
89{
90 init(defaultSampleRate, maxSampleRate);
91}
92
93void
94SipXMediaStackAdapter::init(int defaultSampleRate, int maxSampleRate)
95{
96#ifdef _DEBUG
97
98 #if _WIN64
99 UtlString codecPaths[] = { ".", getExecutableDir().c_str(), "../../../x64/Debug"};
100 #else
101 #if _WIN32
102 UtlString codecPaths[] = { ".", getExecutableDir().c_str(), "../../../Win32/Debug" };
103 #else
104 UtlString codecPaths[] = { "." };
105 #endif
106 #endif
107
108#else
109
110 #if _WIN64
111 UtlString codecPaths[] = { ".", getExecutableDir().c_str(), "../../../x64/Release" };
112 #else
113 #if _WIN32
114 UtlString codecPaths[] = { ".", getExecutableDir().c_str(), "../../../Win32/Release" };
115 #else
116 UtlString codecPaths[] = { "." };
117 #endif
118 #endif
119
120#endif
121
122 int codecPathsNum = sizeof(codecPaths)/sizeof(codecPaths[0]);
123 OsStatus rc = CpTopologyGraphFactoryImpl::addCodecPaths(codecPathsNum, codecPaths);
124 resip_assert(OS_SUCCESS == rc);
125
126 if(mMediaInterfaceMode == sipXConversationMediaInterfaceMode)
127 {
128 OsConfigDb sipXconfig;
129 sipXconfig.set("PHONESET_MAX_ACTIVE_CALLS_ALLOWED",300); // This controls the maximum number of flowgraphs allowed - default is 16
130 mMediaFactory = dynamic_cast<CpTopologyGraphFactoryImpl*>(sipXmediaFactoryFactory(&sipXconfig, 0, maxSampleRate, defaultSampleRate, mLocalAudioEnabled)->getFactoryImplementation());
131 }
132 else
133 {
134 mMediaFactory = dynamic_cast<CpTopologyGraphFactoryImpl*>(sipXmediaFactoryFactory(nullptr, 0, maxSampleRate, defaultSampleRate, mLocalAudioEnabled)->getFactoryImplementation());
135 }
136
137 if (mMediaFactory == nullptr)
138 {
139 CritLog(<< "Error creating media factory for sipX Topology Graph. Cannot start.");
140 exit(-1);
141 }
142
143 if (mEnableExtraPlayAndRecordResources)
144 {
145 if (!addExtraPlayAndRecordResourcesToTopology())
146 {
147 CritLog(<< "Error adjusting resource Topology. Cannot start.");
148 exit(-1);
149 }
150 }
151
152 // Create MediaInterface
153 MpCodecFactory *pCodecFactory = MpCodecFactory::getMpCodecFactory();
154 unsigned int count = 0;
155 const MppCodecInfoV1_1 **codecInfoArray;
156 pCodecFactory->getCodecInfoArray(count, codecInfoArray);
157
158 if(count == 0)
159 {
160 // the default path and CODEC_PLUGINS_FILTER don't appear to work on Linux
161 // also see the call to addCodecPaths above
162 InfoLog(<<"No statically linked codecs or no codecs found with default filter, trying without a filter");
163 pCodecFactory->loadAllDynCodecs(NULL, "");
164 pCodecFactory->getCodecInfoArray(count, codecInfoArray);
165 if(count == 0)
166 {
167 CritLog( << "No static codecs or dynamic codec plugins found in search paths. Cannot start.");
168 exit(-1);
169 }
170 }
171
172 InfoLog( << "Loaded codecs are:");
173 for(unsigned int i =0; i < count; i++)
174 {
175 InfoLog( << " " << codecInfoArray[i]->codecName
176 << "(" << codecInfoArray[i]->codecManufacturer << ") "
177 << codecInfoArray[i]->codecVersion
178 << " MimeSubtype: " << codecInfoArray[i]->mimeSubtype
179 << " Rate: " << codecInfoArray[i]->sampleRate
180 << " Channels: " << codecInfoArray[i]->numChannels);
181 }
182}
183
184void
186{
187 if(mMediaInterfaceMode == sipXGlobalMediaInterfaceMode)
188 {
189 createMediaInterfaceAndMixer(mLocalAudioEnabled /* giveFocus?*/, // This is the one and only media interface - give it focus
190 mMediaInterface,
192 }
193}
194
195void
197{
198 InfoLog(<<"SipXMediaStackAdapter shutdown");
199}
200
202{
203 getBridgeMixer().reset(); // Make sure the mixer is destroyed before the media interface
204 mMediaInterface.reset(); // Make sure inteface is destroyed before factory
205 sipxDestroyMediaFactoryFactory();
206}
207
208void
210{
211 if (mMediaInterface)
212 {
213 // Enable/Disable DTMF digit logging according to UserAgentMasterProfile setting
214 mMediaInterface->allowLoggingDTMFDigits(userAgent->getUserAgentMasterProfile()->dtmfDigitLoggingEnabled());
215 }
216
217 // Note: This is not really required, since we are managing the port allocation - but no harm done
218 // Really not needed now - since FlowManager integration
219 //mMediaFactory->setRtpPortRange(getUserAgent()->getUserAgentMasterProfile()->rtpPortRangeMin(),
220 // getUserAgent()->getUserAgentMasterProfile()->rtpPortRangeMax());
221
222 if(!mRTPPortManager)
223 {
224 mRTPPortManager.reset(new RTPPortManager(getUserAgent()->getUserAgentMasterProfile()->rtpPortRangeMin(), getUserAgent()->getUserAgentMasterProfile()->rtpPortRangeMax()));
225 }
226}
227
230{
231 if (isShuttingDown()) return 0; // Don't allow new things to be created when we are shutting down
232 if (mMediaInterfaceMode == sipXGlobalMediaInterfaceMode)
233 {
234 resip_assert(false);
235 WarningLog(<< "Calling createSharedMediaInterfaceConversation is not appropriate when using sipXGlobalMediaInterfaceMode");
236 return 0;
237 }
238
240
241 CreateConversationCmd* cmd = new CreateConversationCmd(&getConversationManager(), convHandle, autoHoldMode, sharedMediaInterfaceConvHandle);
242 post(cmd);
243 return convHandle;
244}
245
246void
247SipXMediaStackAdapter::outputBridgeMatrixImpl(ConversationHandle convHandle)
248{
249 // Note: convHandle of 0 only makes sense if sipXGlobalMediaInterfaceMode is enabled
250 if (convHandle == 0)
251 {
252 if (getBridgeMixer() != 0)
253 {
254 getBridgeMixer()->outputBridgeMixWeights();
255 }
256 else
257 {
258 WarningLog(<< "ConversationManager::outputBridgeMatrix request with no conversation handle is not appropriate for current MediaInterfaceMode");
259 }
260 }
261 else
262 {
263 Conversation* conversation = getConversation(convHandle);
264 if (conversation)
265 {
266 if (conversation->getBridgeMixer() != 0)
267 {
268 conversation->getBridgeMixer()->outputBridgeMixWeights();
269 }
270 else
271 {
272 WarningLog(<< "ConversationManager::outputBridgeMatrix requested conversation wihtout a mixer/media interface, conversationHandle=" << convHandle);
273 }
274 }
275 else
276 {
277 WarningLog(<< "ConversationManager::outputBridgeMatrix requested for non-existing conversationHandle=" << convHandle);
278 }
279 }
280}
281
282void
284{
285 OsStatus status = mMediaFactory->setSpeakerVolume(volume);
286 if(status != OS_SUCCESS)
287 {
288 WarningLog(<< "setSpeakerVolume failed: status=" << status);
289 }
290}
291
292void
294{
295 OsStatus status = mMediaFactory->setMicrophoneGain(gain);
296 if(status != OS_SUCCESS)
297 {
298 WarningLog(<< "setMicrophoneGain failed: status=" << status);
299 }
300}
301
302void
304{
305 OsStatus status = mMediaFactory->muteMicrophone(mute? TRUE : FALSE);
306 if(status != OS_SUCCESS)
307 {
308 WarningLog(<< "muteMicrophone failed: status=" << status);
309 }
310}
311
312void
314{
315 OsStatus status = mMediaFactory->setAudioAECMode(enable ? MEDIA_AEC_CANCEL : MEDIA_AEC_DISABLED);
316 if(status != OS_SUCCESS)
317 {
318 WarningLog(<< "enableEchoCancel failed: status=" << status);
319 }
320 if(mMediaInterfaceMode == sipXGlobalMediaInterfaceMode) // Note for sipXConversationMediaInterfaceMode - setting will apply on next conversation given focus
321 {
322 mMediaInterface->getInterface()->defocus(); // required to apply changes
323 mMediaInterface->getInterface()->giveFocus();
324 }
325}
326
327void
329{
330 OsStatus status = mMediaFactory->enableAGC(enable ? TRUE : FALSE);
331 if(status != OS_SUCCESS)
332 {
333 WarningLog(<< "enableAutoGainControl failed: status=" << status);
334 }
335 if(mMediaInterfaceMode == sipXGlobalMediaInterfaceMode) // Note for sipXConversationMediaInterfaceMode - setting will apply on next conversation given focus
336 {
337 mMediaInterface->getInterface()->defocus(); // required to apply changes
338 mMediaInterface->getInterface()->giveFocus();
339 }
340}
341
342void
344{
345 OsStatus status = mMediaFactory->setAudioNoiseReductionMode(enable ? MEDIA_NOISE_REDUCTION_MEDIUM /* arbitrary */ : MEDIA_NOISE_REDUCTION_DISABLED);
346 if(status != OS_SUCCESS)
347 {
348 WarningLog(<< "enableNoiseReduction failed: status=" << status);
349 }
350 if(mMediaInterfaceMode == sipXGlobalMediaInterfaceMode) // Note for sipXConversationMediaInterfaceMode - setting will apply on next conversation given focus
351 {
352 mMediaInterface->getInterface()->defocus(); // required to apply changes
353 mMediaInterface->getInterface()->giveFocus();
354 }
355}
356
357void
359 const std::vector<unsigned int>& codecIds, resip::SdpContents& sessionCaps)
360{
361 sessionCaps = SdpContents::Empty; // clear out passed in SdpContents
362
363 // Check if ipaddress is V4 or V6
364 bool v6 = false;
365 if(!ipaddress.empty())
366 {
367 Tuple testTuple(ipaddress, 0, UDP);
368 if(testTuple.ipVersion() == V6)
369 {
370 v6 = true;
371 }
372 }
373
374 // Create Session Capabilities
375 // Note: port, sessionId and version will be replaced in actual offer/answer
376 // Build s=, o=, t=, and c= lines
377 SdpContents::Session::Origin origin("-", 0 /* sessionId */, 0 /* version */, v6 ? SdpContents::IP6 : SdpContents::IP4, ipaddress.empty() ? "0.0.0.0" : ipaddress); // o=
378 SdpContents::Session session(0, origin, "-" /* s= */);
379 session.connection() = SdpContents::Session::Connection(v6 ? SdpContents::IP6 : SdpContents::IP4, ipaddress.empty() ? "0.0.0.0" : ipaddress); // c=
380 session.addTime(SdpContents::Session::Time(0, 0));
381
382 MpCodecFactory *pCodecFactory = MpCodecFactory::getMpCodecFactory();
383 SdpCodecList codecList;
384 pCodecFactory->addCodecsToList(codecList);
385 codecList.bindPayloadTypes();
386
387 //UtlString output;
388 //codecList.toString(output);
389 //InfoLog( << "Codec List: " << output.data());
390
391 // Auto-Create Session Codec Capabilities
392 // Note: port, and potentially payloadid will be replaced in actual offer/answer
393
394 // Build Codecs and media offering
395 SdpContents::Session::Medium medium("audio", 0, 1, "RTP/AVP");
396
397 bool firstCodecAdded = false;
398 for(std::vector<unsigned int>::const_iterator idIter = codecIds.begin();
399 idIter != codecIds.end(); idIter++)
400 {
401 const unsigned int& codecId = *idIter;
402 const SdpCodec* sdpcodec = codecList.getCodec((SdpCodec::SdpCodecTypes)codecId);
403 if(sdpcodec)
404 {
405 UtlString mediaType;
406 sdpcodec->getMediaType(mediaType);
407 // Ensure this codec is an audio codec
408 if(mediaType.compareTo("audio", UtlString::ignoreCase) == 0)
409 {
410 UtlString mimeSubType;
411 sdpcodec->getEncodingName(mimeSubType);
412 //mimeSubType.toUpper();
413
414 int capabilityRate = sdpcodec->getSampleRate();
415 if(mimeSubType == "G722")
416 {
417 capabilityRate = 8000;
418 }
419
420 Data codecName(mimeSubType.data());
421 // The encoding names are not supposed to be case sensitive.
422 // However, some phones, including Polycom, don't recognize
423 // telephone-event if it is not lowercase.
424 // sipXtapi is writing all codec names in uppercase.
425 // (see sipXtapi macro SDP_MIME_SUBTYPE_TO_CASE) and this
426 // hack works around that.
427 // It is more common to use lowercase, so we just lowercase everything.
428 codecName.lowercase();
429
430 SdpContents::Session::Codec codec(codecName, sdpcodec->getCodecPayloadFormat(), capabilityRate);
431 if(sdpcodec->getNumChannels() > 1)
432 {
433 codec.encodingParameters() = Data(sdpcodec->getNumChannels());
434 }
435
436 // Check for telephone-event and add fmtp manually
437 if(mimeSubType.compareTo("telephone-event", UtlString::ignoreCase) == 0)
438 {
439 codec.parameters() = Data("0-15");
440 }
441 else
442 {
443 UtlString fmtpField;
444 sdpcodec->getSdpFmtpField(fmtpField);
445 if(fmtpField.length() != 0)
446 {
447 codec.parameters() = Data(fmtpField.data());
448 }
449 }
450
451 DebugLog(<< "Added codec to session capabilites: id=" << codecId
452 << " type=" << mimeSubType.data()
453 << " rate=" << sdpcodec->getSampleRate()
454 << " plen=" << sdpcodec->getPacketLength()
455 << " payloadid=" << sdpcodec->getCodecPayloadFormat()
456 << " fmtp=" << codec.parameters());
457
458 medium.addCodec(codec);
459 if(!firstCodecAdded)
460 {
461 firstCodecAdded = true;
462
463 // 20 ms of speech per frame (note G711 has 10ms samples, so this is 2 samples per frame)
464 // Note: There are known problems with SDP and the ptime attribute. For now we will choose an
465 // appropriate ptime from the first codec
466 medium.addAttribute("ptime", Data(sdpcodec->getPacketLength() / 1000));
467 }
468 }
469 }
470 }
471
472 session.addMedium(medium);
473 sessionCaps.session() = session;
474}
475
476void
477SipXMediaStackAdapter::createMediaInterfaceAndMixer(bool giveFocus,
478 std::shared_ptr<SipXMediaInterface>& mediaInterface,
479 std::shared_ptr<BridgeMixer>& bridgeMixer)
480{
481 UtlString localRtpInterfaceAddress("127.0.0.1"); // Will be overridden in RemoteParticipantDialogSet, when connection is created anyway
482
483 // Note: STUN and TURN capabilities of the sipX media stack are not used - the FlowManager is responsible for STUN/TURN
484 // TODO SLG - if DISABLE_FLOWMANAGER define is on we should consider enabling stun or turn options
485 mediaInterface = std::make_shared<SipXMediaInterface>(getConversationManager(), (CpTopologyGraphInterface*)mMediaFactory->createMediaInterface(NULL,
486 localRtpInterfaceAddress,
487 0, /* numCodecs - not required at this point */
488 0, /* codecArray - not required at this point */
489 NULL, /* local */
490 mSipXTOSValue, /* TOS Options */
491 NULL, /* STUN Server Address */
492 0, /* STUN Options */
493 25, /* STUN Keepalive period (seconds) */
494 NULL, /* TURN Server Address */
495 0, /* TURN Port */
496 NULL, /* TURN User */
497 NULL, /* TURN Password */
498 25, /* TURN Keepalive period (seconds) */
499 false, /* enable ICE? */
500 0, /* samplesPerSec, 0 = default */
501 nullptr)); /* pDispatcher - set below in setNotificationDispatcher call */
502
503 // Register the NotificationDispatcher class (derived from OsMsgDispatcher)
504 // as the sipX notification dispatcher
505 mediaInterface->getInterface()->setNotificationDispatcher(mediaInterface.get());
506
507 // Turn on notifications for all resources...
508 mediaInterface->getInterface()->setNotificationsEnabled(true);
509
510 // If we have a user agent set DTMF logging now, otherwise wait until setUserAgent is called
511 if (getUserAgent())
512 {
513 // Enable/Disable DTMF digit logging according to UserAgentMasterProfile setting
514 mediaInterface->allowLoggingDTMFDigits(getUserAgent()->getUserAgentMasterProfile()->dtmfDigitLoggingEnabled());
515 }
516
517 if(giveFocus)
518 {
519 mediaInterface->getInterface()->giveFocus();
520 }
521
522 bridgeMixer = std::make_shared<SipXBridgeMixer>(*(mediaInterface->getInterface()));
523}
524
525bool
530
531bool
533{
534 resip_assert(conversation1);
535 resip_assert(conversation2);
536
537 // You can only add non-local (excluding RemoteIM) participants to 2 different conversations if they share the same MediaInterface
538 return (((SipXConversation*)conversation1)->getMediaInterface().get() == ((SipXConversation*)conversation2)->getMediaInterface().get());
539}
540
543 RelatedConversationSet* relatedConversationSet, // Pass NULL to create new RelatedConversationSet
544 ConversationHandle sharedMediaInterfaceConvHandle,
546{
547 return new SipXConversation(handle, getConversationManager(), *this, relatedConversationSet, sharedMediaInterfaceConvHandle, autoHoldMode);
548}
549
555
557SipXMediaStackAdapter::createMediaResourceParticipantInstance(ParticipantHandle partHandle, const resip::Uri& mediaUrl, const std::shared_ptr<resip::Data>& playAudioBuffer, void* recordingCircularBuffer)
558{
559 return new SipXMediaResourceParticipant(partHandle, getConversationManager(), *this, mediaUrl, playAudioBuffer, recordingCircularBuffer);
560}
561
567
573
577 std::shared_ptr<ConversationProfile> conversationProfile)
578{
579 return new SipXRemoteParticipantDialogSet(getConversationManager(), *this, forkSelectMode, conversationProfile);
580}
581
582bool
583SipXMediaStackAdapter::addExtraPlayAndRecordResourcesToTopology()
584{
585 MpResourceTopology* resourceTopology = mMediaFactory->getInitialResourceTopology();
586
587 // Add in first extra player (FromFile) resource
588 OsStatus result = resourceTopology->addResource(DEFAULT_FROM_FILE_RESOURCE_TYPE, DEFAULT_FROM_FILE_2_RESOURCE_NAME, MP_INVALID_CONNECTION_ID, -1);
589 resip_assert(result == OS_SUCCESS);
590 if (result == OS_SUCCESS)
591 {
592 // Add in second extra player (FromFile) resource
593 result = resourceTopology->addResource(DEFAULT_FROM_FILE_RESOURCE_TYPE, DEFAULT_FROM_FILE_3_RESOURCE_NAME, MP_INVALID_CONNECTION_ID, -1);
594 }
595 resip_assert(result == OS_SUCCESS);
596 if (result == OS_SUCCESS)
597 {
598 // Add in extra recording resource
599 result = resourceTopology->addResource(DEFAULT_RECORDER_RESOURCE_TYPE, DEFAULT_RECORDER_2_RESOURCE_NAME, MP_INVALID_CONNECTION_ID, -1);
600 }
601
602 resip_assert(result == OS_SUCCESS);
603 if (result == OS_SUCCESS)
604 {
605 // Add connection for first extra player
606 result = resourceTopology->addConnection(DEFAULT_FROM_FILE_2_RESOURCE_NAME, 0, DEFAULT_BRIDGE_RESOURCE_NAME, MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT);
607 }
608 resip_assert(result == OS_SUCCESS);
609 if (result == OS_SUCCESS)
610 {
611 // Add connection for second extra player
612 result = resourceTopology->addConnection(DEFAULT_FROM_FILE_3_RESOURCE_NAME, 0, DEFAULT_BRIDGE_RESOURCE_NAME, MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT);
613 }
614 resip_assert(result == OS_SUCCESS);
615 if (result == OS_SUCCESS)
616 {
617 // Add connection for extra recording resource
618 result = resourceTopology->addConnection(DEFAULT_BRIDGE_RESOURCE_NAME, MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT, DEFAULT_RECORDER_2_RESOURCE_NAME, 0);
619 }
620 resip_assert(result == OS_SUCCESS);
621
622 //UtlString resourcesDump;
623 //resourceTopology->dumpResources(resourcesDump);
624 //UtlString connectionsDump;
625 //resourceTopology->dumpConnections(connectionsDump);
626 //cout << resourcesDump.data();
627 //cout << connectionsDump.data();
628
629 return result == OS_SUCCESS;
630}
631
632void
633SipXMediaStackAdapter::process()
634{
635 // do nothing
636}
637
638void
639SipXMediaStackAdapter::setRTCPEventLoggingHandler(std::shared_ptr<flowmanager::RTCPEventLoggingHandler> h)
640{
641 getFlowManager().setRTCPEventLoggingHandler(h);
643}
644
645void
646SipXMediaStackAdapter::initializeDtlsFactory(const resip::Data& defaultAoR)
647{
648 getFlowManager().initializeDtlsFactory(defaultAoR.c_str());
649}
650
651
652/* ====================================================================
653
654 Copyright (c) 2021-2022, SIP Spectrum, Inc. www.sipspectrum.com
655 Copyright (c) 2021, Daniel Pocock https://danielpocock.com
656 Copyright (c) 2007-2008, Plantronics, Inc.
657 All rights reserved.
658
659 Redistribution and use in source and binary forms, with or without
660 modification, are permitted provided that the following conditions are
661 met:
662
663 1. Redistributions of source code must retain the above copyright
664 notice, this list of conditions and the following disclaimer.
665
666 2. Redistributions in binary form must reproduce the above copyright
667 notice, this list of conditions and the following disclaimer in the
668 documentation and/or other materials provided with the distribution.
669
670 3. Neither the name of Plantronics nor the names of its contributors
671 may be used to endorse or promote products derived from this
672 software without specific prior written permission.
673
674 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
675 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
676 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
677 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
678 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
679 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
680 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
681 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
682 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
683 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
684 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
685
686 ==================================================================== */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define CritLog(args_)
Definition Logger.hxx:140
#define WarningLog(args_)
Definition Logger.hxx:134
#define resip_assert(x)
This file needs to work for both C and C++ code.
void setRTCPEventLoggingHandler(std::shared_ptr< RTCPEventLoggingHandler > handler) noexcept
void initializeDtlsFactory(const char *certAor)
virtual void outputBridgeMixWeights()=0
Logs a multiline representation of the current state of the mixing matrix.
This class is one of two main classes of concern to an application using the UserAgent library.
This class is used to manage membership of participants.
BridgeMixer * getBridgeMixer() noexcept
The classes defined here are used to pass commands from the application thread to the UserAgent threa...
This class represents a local participant.
This class represents a media resource participant.
This class is one of two main classes of concern to an application.
ConversationManager & getConversationManager()
Conversation * getConversation(ConversationHandle convHandle)
virtual UserAgent * getUserAgent()
ConversationHandle getNewConversationHandle()
std::shared_ptr< BridgeMixer > & getBridgeMixer()
virtual void setRTCPEventLoggingHandler(std::shared_ptr< flowmanager::RTCPEventLoggingHandler > h)
void post(resip::Message *message)
This is used to keep a mapping between all related conversations.
This class is used by Invite DialogSets.
This class represent a remote participant.
This class is used to manage membership of participants.
This class represents a local participant.
This class represents a media resource participant.
virtual void conversationManagerReady(ConversationManager *conversationManager) override
virtual bool supportsMultipleMediaInterfaces() override
virtual void buildSessionCapabilities(const resip::Data &ipaddress, const std::vector< unsigned int > &codecIds, resip::SdpContents &sessionCaps) override
Builds a session capabilties SDPContents based on the passed in ipaddress and codec ordering.
virtual LocalParticipant * createLocalParticipantInstance(ParticipantHandle partHandle) override
virtual void setUserAgent(UserAgent *userAgent) override
virtual void setMicrophoneGain(int gain)
virtual void enableEchoCancel(bool enable)
SipXMediaStackAdapter(ConversationManager &conversationManager, bool localAudioEnabled=true, MediaInterfaceMode mediaInterfaceMode=sipXGlobalMediaInterfaceMode, bool enableExtraPlayAndRecordResources=false)
virtual bool canConversationsShareParticipants(Conversation *conversation1, Conversation *conversation2) override
static constexpr char DEFAULT_FROM_FILE_2_RESOURCE_NAME[]
virtual void setSpeakerVolume(int volume)
static constexpr char DEFAULT_RECORDER_2_RESOURCE_NAME[]
virtual void muteMicrophone(bool mute)
MediaInterfaceMode getMediaInterfaceMode() const
virtual RemoteParticipantDialogSet * createRemoteParticipantDialogSetInstance(ConversationManager::ParticipantForkSelectMode forkSelectMode=ConversationManager::ForkSelectAutomatic, std::shared_ptr< ConversationProfile > conversationProfile=nullptr) override
virtual void enableAutoGainControl(bool enable)
static constexpr char DEFAULT_FROM_FILE_3_RESOURCE_NAME[]
virtual Conversation * createConversationInstance(ConversationHandle handle, RelatedConversationSet *relatedConversationSet, ConversationHandle sharedMediaInterfaceConvHandle, ConversationManager::AutoHoldMode autoHoldMode) override
virtual void enableNoiseReduction(bool enable)
virtual MediaResourceParticipant * createMediaResourceParticipantInstance(ParticipantHandle partHandle, const resip::Uri &mediaUrl, const std::shared_ptr< resip::Data > &playAudioBuffer, void *recordingCircularBuffer) override
virtual ConversationHandle createSharedMediaInterfaceConversation(ConversationHandle sharedMediaInterfaceConvHandle, ConversationManager::AutoHoldMode autoHoldMode=ConversationManager::AutoHoldEnabled)
Only applicable if sipXConversationMediaInterfaceMode is used.
virtual RemoteParticipant * createRemoteParticipantInstance(resip::DialogUsageManager &dum, RemoteParticipantDialogSet &rpds) override
MediaInterfaceMode
Note: sipXtapi Media Interfaces have a finite number of supported endpoints that are allowed in each ...
This class is one of two main classes of concern to an application using the UserAgent library.
Definition UserAgent.hxx:56
std::shared_ptr< UserAgentMasterProfile > getUserAgentMasterProfile() const noexcept
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Data & lowercase()
Converts this Data to lowercase.
Definition Data.cxx:1635
parameters for a specific codec are stored in this class.
const Data & encodingParameters() const
returns the encoding parameters associated with this codec
const Data & parameters() const
returns the parameters associated with this codec
Process c= (connection) lines in SDP.
process m= (media announcement) blocks
void addAttribute(const Data &key, const Data &value=Data::Empty)
add a media attribute line
void addCodec(const Codec &codec)
add a codec to the m= line
processes o= lines in SDP
Process t= (start/stop time) lines in SDP.
Provides an interface to read and modify SDP bodies.
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
static const SdpContents Empty
Session & session()
get the parsed SDP
Represents a network address.
Definition Tuple.hxx:59
IpVersion ipVersion() const
Returns V4 or V6 as appropriate.
Definition Tuple.cxx:537
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Definition Uri.hxx:22
unsigned int ConversationHandle
unsigned int ParticipantHandle
dcm! – add UnusedChecking(_enum) below;