⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lidep.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * lidep.cxx
 *
 * Line Interface Device EndPoint
 *
 * Open Phone Abstraction Library
 *
 * Copyright (c) 2001 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.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: lidep.cxx,v $
 * Revision 1.1  2006/06/26 03:03:21  joegenbaclor
 * I have decided to include the latest development realease  of OPAL tagged Deimos Devel 1 (June 8 2006) as inegrated classes to opensipstack to avoid future version conflicts due to the fast pace in OPAL development.   This move is also aimed to reduce the size of projects using OPAL componets such as the soon to be relased OpenSIPPhone.
 *
 * Revision 2.27  2006/03/08 10:38:01  csoutheren
 * Applied patch #1441139 - virtualise LID functions and kill monitorlines correctly
 * Thanks to Martin Yarwood
 *
 * Revision 2.26  2006/01/14 10:43:06  dsandras
 * Applied patch from Brian Lu <Brian.Lu _AT_____ sun.com> to allow compilation
 * with OpenSolaris compiler. Many thanks !!!
 *
 * Revision 2.25  2004/10/06 13:03:42  rjongbloed
 * Added "configure" support for known LIDs
 * Changed LID GetName() function to be normalised against the GetAllNames()
 *   return values and fixed the pre-factory registration system.
 * Added a GetDescription() function to do what the previous GetName() did.
 *
 * Revision 2.24  2004/08/14 07:56:31  rjongbloed
 * Major revision to utilise the PSafeCollection classes for the connections and calls.
 *
 * Revision 2.23  2004/07/11 12:42:12  rjongbloed
 * Added function on endpoints to get the list of all media formats any
 *   connection the endpoint may create can support.
 *
 * Revision 2.22  2004/05/24 13:52:30  rjongbloed
 * Added a separate structure for the silence suppression paramters to make
 *   it easier to set from global defaults in the manager class.
 *
 * Revision 2.21  2004/05/17 13:24:18  rjongbloed
 * Added silence suppression.
 *
 * Revision 2.20  2004/04/25 08:34:08  rjongbloed
 * Fixed various GCC 3.4 warnings
 *
 * Revision 2.19  2004/04/18 13:35:27  rjongbloed
 * Fixed ability to make calls where both endpoints are specified a priori. In particular
 *   fixing the VXML support for an outgoing sip/h323 call.
 *
 * Revision 2.18  2003/06/02 02:56:41  rjongbloed
 * Moved LID specific media stream class to LID source file.
 *
 * Revision 2.17  2003/03/24 07:18:29  robertj
 * Added registration system for LIDs so can work with various LID types by
 *   name instead of class instance.
 *
 * Revision 2.16  2003/03/17 10:26:59  robertj
 * Added video support.
 *
 * Revision 2.15  2003/03/06 03:57:47  robertj
 * IVR support (work in progress) requiring large changes everywhere.
 *
 * Revision 2.14  2002/09/04 05:28:14  robertj
 * Added ability to set default line name to be used when the destination
 *   does not match any lines configured.
 *
 * Revision 2.13  2002/04/09 00:18:39  robertj
 * Added correct setting of originating flag when originating the connection.
 *
 * Revision 2.12  2002/01/22 05:16:59  robertj
 * Revamp of user input API triggered by RFC2833 support
 *
 * Revision 2.11  2001/11/14 01:31:55  robertj
 * Corrected placement of adjusting media format list.
 *
 * Revision 2.10  2001/11/13 06:25:56  robertj
 * Changed SetUpConnection() so returns BOOL as returning
 *   pointer to connection is not useful.
 *
 * Revision 2.9  2001/10/15 04:31:56  robertj
 * Removed answerCall signal and replaced with state based functions.
 *
 * Revision 2.8  2001/10/04 00:47:02  robertj
 * Removed redundent parameter.
 *
 * Revision 2.7  2001/08/23 05:51:17  robertj
 * Completed implementation of codec reordering.
 *
 * Revision 2.6  2001/08/23 03:15:51  robertj
 * Added missing Lock() calls in SetUpConnection
 *
 * Revision 2.5  2001/08/22 10:20:09  robertj
 * Changed connection locking to use double mutex to guarantee that
 *   no threads can ever deadlock or access deleted connection.
 *
 * Revision 2.4  2001/08/17 08:36:48  robertj
 * Moved call end reasons enum from OpalConnection to global.
 * Fixed missing mutex on connections structure..
 *
 * Revision 2.3  2001/08/17 01:11:17  robertj
 * Added ability to add whole LID's to LID endpoint.
 *
 * Revision 2.2  2001/08/01 06:23:55  robertj
 * Changed to use separate mutex for LIDs structure to avoid Unix nested mutex problem.
 *
 * Revision 2.1  2001/08/01 05:24:01  robertj
 * Made OpalMediaFormatList class global to help with documentation.
 * Made the connections media format list to come from LID.
 *
 * Revision 2.0  2001/07/27 15:48:25  robertj
 * Conversion of OpenH323 to Open Phone Abstraction Library (OPAL)
 *
 */

#include <ptlib.h>

#ifdef __GNUC__
#pragma implementation "lidep.cxx"
#endif

#include <lids/lidep.h>

#include <opal/manager.h>
#include <opal/call.h>
#include <opal/patch.h>


#define new PNEW

/////////////////////////////////////////////////////////////////////////////

OpalLIDEndPoint::OpalLIDEndPoint(OpalManager & mgr,
                                 const PString & prefix,
                                 unsigned attributes)
  : OpalEndPoint(mgr, prefix, attributes),
    defaultLine("*")
{
  monitorThread = PThread::Create(PCREATE_NOTIFIER(MonitorLines), 0,
                                  PThread::NoAutoDeleteThread,
                                  PThread::LowPriority,
                                  prefix.ToUpper() & "Line Monitor");
}


OpalLIDEndPoint::~OpalLIDEndPoint()
{
  if(NULL != monitorThread)
  {
     PTRACE(3, "LID EP\tAwaiting monitor thread termination " << GetPrefixName());
     exitFlag.Signal();
     monitorThread->WaitForTermination();
     delete monitorThread;
     monitorThread = NULL;
  }
}


BOOL OpalLIDEndPoint::MakeConnection(OpalCall & call,
                                     const PString & remoteParty,
                                     void * userData)
{
  // First strip of the prefix if present
  PINDEX prefixLength = 0;
  if (remoteParty.Find(GetPrefixName()+":") == 0)
    prefixLength = GetPrefixName().GetLength()+1;

  // Then see if there is a specific line mentioned
  PString number, lineName;
  PINDEX at = remoteParty.Find('@', prefixLength);
  if (at != P_MAX_INDEX) {
    number = remoteParty(prefixLength, at);
    lineName = remoteParty.Mid(at+1);
  }
  else {
    if (HasAttribute(CanTerminateCall))
      lineName = remoteParty.Mid(prefixLength);
    else
      number = remoteParty.Mid(prefixLength);
  }

  if (lineName.IsEmpty())
    lineName = '*';

  // Locate a line
  OpalLine * line = GetLine(lineName, TRUE);
  if (line == NULL)
    line = GetLine(defaultLine, TRUE);
  if (line == NULL)
    return FALSE;

  OpalLineConnection * connection = CreateConnection(call, *line, userData, number);
  connectionsActive.SetAt(connection->GetToken(), connection);

  // If we are the A-party then need to initiate a call now in this thread. If
  // we are the B-Party then SetUpConnection() gets called in the context of
  // the A-party thread.
  if (call.GetConnection(0) == (OpalConnection*)connection)
    connection->SetUpConnection();

  return TRUE;
}


OpalMediaFormatList OpalLIDEndPoint::GetMediaFormats() const
{
  OpalMediaFormatList mediaFormats;
  AddVideoMediaFormats(mediaFormats);

  PWaitAndSignal mutex(linesMutex);

  for (PINDEX i = 0; i < lines.GetSize(); i++) {
    OpalMediaFormatList devFormats = lines[i].GetDevice().GetMediaFormats();
    for (PINDEX j = 0; j < devFormats.GetSize(); j++)
      mediaFormats += devFormats[j];
  }

  return mediaFormats;
}


OpalLineConnection * OpalLIDEndPoint::CreateConnection(OpalCall & call,
                                                       OpalLine & line,
                                                       void * /*userData*/,
                                                       const PString & number)
{
  return new OpalLineConnection(call, *this, line, number);
}


static void InitialiseLine(OpalLine * line)
{
  line->Ring(0);
  line->StopTone();
  line->StopRawCodec();
  line->StopReadCodec();
  line->StopWriteCodec();
  line->DisableAudio();

  for (unsigned lnum = 0; lnum < line->GetDevice().GetLineCount(); lnum++) {
    if (lnum != line->GetLineNumber())
      line->GetDevice().SetLineToLineDirect(lnum, line->GetLineNumber(), FALSE);
  }
}


BOOL OpalLIDEndPoint::AddLine(OpalLine * line)
{
  if (PAssertNULL(line) == NULL)
    return FALSE;

  if (!line->GetDevice().IsOpen())
    return FALSE;

  if (line->IsTerminal() != HasAttribute(CanTerminateCall))
    return FALSE;

  InitialiseLine(line);

  linesMutex.Wait();
  lines.Append(line);
  linesMutex.Signal();

  return TRUE;
}


void OpalLIDEndPoint::RemoveLine(OpalLine * line)
{
  linesMutex.Wait();
  lines.Remove(line);
  linesMutex.Signal();
}


void OpalLIDEndPoint::RemoveLine(const PString & token)
{
  linesMutex.Wait();
  for (PINDEX i = 0; i < lines.GetSize(); i++) {
    if (lines[i].GetToken() *= token)
      lines.RemoveAt(i--);
  }
  linesMutex.Signal();
}


void OpalLIDEndPoint::RemoveAllLines()
{
  linesMutex.Wait();
  lines.RemoveAll();
  devices.RemoveAll();
  linesMutex.Signal();
}


BOOL OpalLIDEndPoint::AddLinesFromDevice(OpalLineInterfaceDevice & device)
{
  if (!device.IsOpen())
    return FALSE;

  BOOL atLeastOne = FALSE;

  linesMutex.Wait();

  for (unsigned line = 0; line < device.GetLineCount(); line++) {
    if (device.IsLineTerminal(line) == HasAttribute(CanTerminateCall)) {
      OpalLine * newLine = new OpalLine(device, line);
      InitialiseLine(newLine);
      lines.Append(newLine);
      atLeastOne = TRUE;
    }
  }

  linesMutex.Signal();

  return atLeastOne;
}


void OpalLIDEndPoint::RemoveLinesFromDevice(OpalLineInterfaceDevice & device)
{
  linesMutex.Wait();
  for (PINDEX i = 0; i < lines.GetSize(); i++) {
    if (lines[i].GetToken().Find(device.GetDeviceName()) == 0)
      lines.RemoveAt(i--);
  }
  linesMutex.Signal();
}


BOOL OpalLIDEndPoint::AddDeviceNames(const PStringArray & descriptors)
{
  BOOL ok = FALSE;

  for (PINDEX i = 0; i < descriptors.GetSize(); i++) {
    if (AddDeviceName(descriptors[i]))
      ok = TRUE;
  }

  return ok;
}


BOOL OpalLIDEndPoint::AddDeviceName(const PString & descriptor)
{
  PINDEX colon = descriptor.Find(':');
  if (colon == P_MAX_INDEX)
    return FALSE;

  PString deviceType = descriptor.Left(colon).Trim();
  PString deviceName = descriptor.Mid(colon+1).Trim();

  // Make sure not already there.
  linesMutex.Wait();
  for (PINDEX i = 0; i < devices.GetSize(); i++) {
    if (devices[i].GetDeviceType() == deviceType && devices[i].GetDeviceName() == deviceName) {
      linesMutex.Signal();
      return TRUE;
    }
  }
  linesMutex.Signal();

  // Not there so add it.
  OpalLineInterfaceDevice * device = OpalLineInterfaceDevice::Create(deviceType);
  if (device == NULL)
    return FALSE;

  if (device->Open(deviceName))
    return AddDevice(device);

  delete device;
  return FALSE;
}


BOOL OpalLIDEndPoint::AddDevice(OpalLineInterfaceDevice * device)
{
  if (PAssertNULL(device) == NULL)
    return FALSE;

  linesMutex.Wait();
  devices.Append(device);
  linesMutex.Signal();
  return AddLinesFromDevice(*device);
}


void OpalLIDEndPoint::RemoveDevice(OpalLineInterfaceDevice * device)
{
  if (PAssertNULL(device) == NULL)
    return;

  RemoveLinesFromDevice(*device);
  linesMutex.Wait();
  devices.Remove(device);
  linesMutex.Signal();
}


OpalLine * OpalLIDEndPoint::GetLine(const PString & lineName, BOOL enableAudio) const
{
  PWaitAndSignal mutex(linesMutex);

  for (PINDEX i = 0; i < lines.GetSize(); i++) {
    if ((lineName == "*" || lines[i].GetDescription() == lineName) &&
        (!enableAudio || lines[i].EnableAudio()))
      return &lines[i];
  }

  return NULL;
}


void OpalLIDEndPoint::SetDefaultLine(const PString & lineName)
{
  linesMutex.Wait();
  defaultLine = lineName;
  linesMutex.Signal();
}


void OpalLIDEndPoint::MonitorLines(PThread &, INT)
{
  PTRACE(3, "LID EP\tMonitor thread started for " << GetPrefixName());

  while (!exitFlag.Wait(100)) {
    linesMutex.Wait();
    for (PINDEX i = 0; i < lines.GetSize(); i++)
      MonitorLine(lines[i]);
    linesMutex.Signal();
  }

  PTRACE(3, "LID EP\tMonitor thread stopped for " << GetPrefixName());
}


void OpalLIDEndPoint::MonitorLine(OpalLine & line)
{
  PSafePtr<OpalLineConnection> connection = GetLIDConnectionWithLock(line.GetToken());
  if (connection != NULL) {
    // Are still in a call, pass hook state it to the connection object for handling
    connection->Monitor(!line.IsDisconnected());
    return;
  }

  if (line.IsAudioEnabled()) {
    // Are still in previous call, wait for them to hang up
    if (line.IsDisconnected()) {
      PTRACE(3, "LID EP\tLine " << line << " has disconnected.");
      line.StopTone();
      line.DisableAudio();
    }
    return;
  }

  if (line.IsTerminal()) {
    // Not off hook, so nothing happening, just return
    if (!line.IsOffHook())
      return;
    PTRACE(3, "LID EP\tLine " << line << " has gone off hook.");
  }
  else {
    // Not ringing, so nothing happening, just return
    if (!line.IsRinging())
      return;
    PTRACE(3, "LID EP\tLine " << line << " is ringing.");
  }

  // See if we can get exlusive use of the line. With something like a LineJACK

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -