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

📄 conference.cxx

📁 openmcu 是开源的H.323会议服务器,需要pwlib 和 openh323的编译库文件支持。
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * conference.cxx
 *
 * Conferencing functions for a simple MCU
 *
 * Copyright (c) 2000 Equivalence Pty. Ltd.
 * Copyright (c) 2004 Post Increment
 *
 * 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 Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions of this code were written by Post Increment (http://www.postincrement.com) 
 * with the assistance of funding from Citron Networks (http://www.citron.com.tw)
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): Derek J Smithies (derek@indranet.co.nz)
 *                 ------------------------------
 *
 * $Log: conference.cxx,v $
 * Revision 2.5  2004/09/22 22:39:26  csoutheren
 * Fixed race condition, thanks to Neil McCurdy
 *
 * Revision 2.4  2004/05/26 06:54:31  csoutheren
 * Changed to be a PHTTPServiceProcess
 * Added ability to play WAV files on member entry and exit
 * Added additional documentation on all classes
 * Preparation for re-introducing video
 *
 * Revision 2.3  2004/03/31 03:36:38  csoutheren
 * Fixed problem with user indication messages
 * Fixed problems with room listener and unlisten
 *
 * Revision 2.2  2004/03/30 11:27:23  csoutheren
 * Reverted to old mixing algorithm
 *
 * Revision 2.1  2004/03/23 11:40:06  csoutheren
 * Fixed problem where deleting map element in-place causes crash at end of call
 * Fixed problem where referencing map by iterator rather than ID
 * Fixed code formatting problems
 *
 * Revision 2.0  2004/03/08 02:06:24  csoutheren
 * Totally rewritten to use new connection locking mecahnism
 * Added ability to monitor conferences
 * Added initial support for H.323 MCU messages
 * Thanks to Citron Networks for supporting this work
 *
 */

#include <ptlib.h>

#include "conference.h"

// size of a PCM data packet, in samples
#define PCM_PACKET_LEN          240

// size of a PCM data buffer, in bytes
#define PCM_BUFFER_LEN          (PCM_PACKET_LEN * 2)

// number of PCM buffers to keep
#define PCM_BUFFER_COUNT        2

#define PCM_BUFFER_SIZE         (PCM_BUFFER_LEN * PCM_BUFFER_COUNT)

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

ConferenceManager::ConferenceManager()
{
}

Conference * ConferenceManager::MakeConference(const PString & roomToCreate, const PString & name)
{
  OpalGloballyUniqueID conferenceID;
  {
    PWaitAndSignal m(conferenceListMutex);
    ConferenceList::const_iterator r;
    for (r = conferenceList.begin(); r != conferenceList.end(); ++r) {
      if (roomToCreate == r->second->GetNumber()) {
        conferenceID = r->second->GetID();
        break;
      }
    }
  }

  return MakeConference(conferenceID, roomToCreate, name);
}


Conference * ConferenceManager::MakeConference(const OpalGloballyUniqueID & conferenceID, 
                                                 const PString & roomToCreate, 
                                                 const PString & name)
{
  Conference * conference = NULL;
  BOOL newConference = FALSE;
  {
    PWaitAndSignal m(conferenceListMutex);
    ConferenceList::const_iterator r = conferenceList.find(conferenceID);
    if (r != conferenceList.end())
      conference = r->second;
    else {
      conference = CreateConference(conferenceID, roomToCreate, name);
      conferenceList.insert(std::pair<OpalGloballyUniqueID, Conference *>(conferenceID, conference));
      newConference = TRUE;
    }
  }

  if (newConference)
    OnCreateConference(conference);

  return conference;
}

Conference * ConferenceManager::CreateConference(const OpalGloballyUniqueID & _guid,
                                                              const PString & _number,
                                                              const PString & _name)
{ 
  return new Conference(*this, _guid, _number, _name); 
}


BOOL ConferenceManager::HasConference(const OpalGloballyUniqueID & conferenceID)
{
  PWaitAndSignal m(conferenceListMutex);
  ConferenceList::const_iterator r = conferenceList.find(conferenceID);
  return r != conferenceList.end();
}

BOOL ConferenceManager::HasConference(const PString & number)
{
  PWaitAndSignal m(conferenceListMutex);
  ConferenceList::const_iterator r;
  for (r = conferenceList.begin(); r != conferenceList.end(); ++r) {
    if (r->second->GetNumber() == number)
      return TRUE;
  }
  return FALSE;
}

void ConferenceManager::RemoveConference(const OpalGloballyUniqueID & confId)
{
  PWaitAndSignal m(conferenceListMutex);
  ConferenceList::iterator r = conferenceList.find(confId);
  if (r != conferenceList.end())  {
    Conference * conf = r->second;
    OnDestroyConference(conf);
    conferenceList.erase(confId);
    delete conf;
  }
}

void ConferenceManager::RemoveMember(const OpalGloballyUniqueID & confId, ConferenceMember * toRemove)
{
  Conference * conf = toRemove->GetConference();
  BOOL removeConf = conf->RemoveMember(toRemove);
  delete toRemove;
  if (removeConf)
    RemoveConference(conf->GetID());
}

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

Conference::Conference(        ConferenceManager & _manager,
                       const OpalGloballyUniqueID & _guid,
                                    const PString & _number,
                                    const PString & _name)
  : manager(_manager), guid(_guid), number(_number), name(_name)
{ 
  //memberList.DisallowDeleteObjects();

  PTRACE(3, "Conference\tNew conference started: ID=" << guid << ", number = " << number);

#ifndef NO_MCU_VIDEO

  // if this is the first connection to a room, create the video buffer.
  if (create_new_room) {
    //cout << "CREATING VIDEO BUFFER FOR "<<newRoomID<<endl;
    videoBufferDict.SetAt(newRoomID, new VideoBuffer);

    VideoBuffer & videoBuffer = videoBufferDict[newRoomID];
    if (videoLarge)
      videoBuffer.SetSize(352,288);


    // create the spoken list.
    spokenListDict.SetAt(newRoomID, new PStringList);
    if (singleStream) {
      PStringList & spokenList = spokenListDict[newRoomID];
      spokenList.AppendString(newToken);
    }


    // create the position list.
    videoPosnDict.SetAt(newRoomID, new PStringList);

    PStringList & videoPosnList = videoPosnDict[newRoomID];

    if (singleStream) {
      videoPosnList.AppendString("");
    } else {
      PINDEX i;
      for(i=0;i<4;i++)  // hard coded to support 4 images
        videoPosnList.AppendString("");
    }
  }


  // Normally we display the video for the "active" users, ie
  // people who are currently speaking (based on noise detection)
  //
  // If there are currently less than 4 members then we can display
  // the video right from the start, before they begin talking.
  // This is also handy for connections with video, but no audio.
  //
  // Problem is finding out whether or not an ep sends video.
  // That is for a coming version.

  if (singleStream) {
    //only first connection must send video
    if (create_new_room) {
      AddVideoPosnToken(newToken,newRoomID);
    }
  } else {
    AddVideoPosnToken(newToken,newRoomID);
  }

#endif
}

Conference::~Conference()
{
}

void Conference::AddMember(ConferenceMember * memberToAdd)
{
  PTRACE(3, "Conference\tAdding member " << memberToAdd->GetName() << " to conference " << guid);
  cout << memberToAdd->GetName() << " joining conference " << number << "(" << guid << ")" << endl;

  // add the member to the conference
  memberToAdd->AddToConference(this);

  {
    // lock the member list
    PWaitAndSignal m(memberListMutex);

    // add this member to the conference member list
    memberList.insert(std::pair<void *, ConferenceMember *>(memberToAdd->GetID(), memberToAdd));

    // make sure each member has a connection created for the new member
    // make sure the new member has a connection created for reach existing member
    std::map<void *, ConferenceMember *>::const_iterator r;
    for (r = memberList.begin(); r != memberList.end(); r++) {
      ConferenceMember * conn = r->second;
      if (conn != memberToAdd) {
        conn->AddConnection(memberToAdd);
        memberToAdd->AddConnection(conn);
      }
    }
  }

  // call the callback function
  OnMemberJoining(memberToAdd);
}

BOOL Conference::RemoveMember(ConferenceMember * memberToRemove)
{
  PTRACE(3, "Conference\tRemoving call " << memberToRemove->GetName() << " from conference " << guid << " with size " << (PINDEX)memberList.size());
  cout << memberToRemove->GetName() << " leaving conference " << number << "(" << guid << ")" << endl;

  BOOL result;
  {
    PWaitAndSignal m(memberListMutex);

    // remove this member from the connection lists for all other members
    std::map<void *, ConferenceMember *>::iterator r;
    for (r = memberList.begin(); r != memberList.end(); r++) {
      ConferenceMember * conn = r->second;
      if (conn != memberToRemove) 
        r->second->RemoveConnection(memberToRemove->GetID());
    }

    // remove this connection from the member list
    memberList.erase(memberToRemove->GetID());

    // return TRUE if conference is empty
    result = memberList.size() == 0;
  }

  // call the callback function
  if (!result)
    OnMemberLeaving(memberToRemove);

  return result;
}

#ifndef NO_MCU_VIDEO
PINDEX Conference::FindTokensVideoPosn(const PString & thisToken,
                                           const PString & roomID)
{
  PStringList & videoPosnList = videoPosnDict[roomID];
  PINDEX keyIndex;
  for (keyIndex = 0; keyIndex<videoPosnList.GetSize(); keyIndex++)
    if (thisToken == videoPosnList[keyIndex] )
      return keyIndex;
  
  return P_MAX_INDEX;
}

BOOL Conference::AddVideoPosnToken(const PString & thisToken,
                                       const PString & roomID)
{
  PStringList & videoPosnList = videoPosnDict[roomID];
  PINDEX keyIndex;
  for (keyIndex = 0; keyIndex<videoPosnList.GetSize(); keyIndex++)
    if (videoPosnList[keyIndex] == "" ) {
      videoPosnList[keyIndex] = thisToken;
      return TRUE;
    }
  
  return FALSE;
}

#endif

#if 0
BOOL Conference::WriteAudio(OpenMCUH323Connection * source, const void * buffer, PINDEX amount)
{
  //The spokenList construct is required to determine who were the last
  //to speak, which is needed for determining which four videoimages are displayed.
  //spokenList contains a sorted list of when the last packet was received from
  //which connection. Thus, when an audio packet is received from a connection,
  //the name of the connection is moved to the end of the list.

  // If someone new comes along, everyone moves down.
#ifndef NO_MCU_VIDEO
  if ( DetectNoise(buffer,amount) && !singleStream ) {
    PStringList & spokenList = spokenListDict[roomID];
    PINDEX keyIndex = spokenList.GetStringsIndex(thisToken);
    if (keyIndex != P_MAX_INDEX)
      spokenList.RemoveAt(keyIndex);
    spokenList.AppendString(thisToken);  
    if (FindTokensVideoPosn(thisToken,roomID) != P_MAX_INDEX)
      goto processAudio;

    if (!singleStream && AddVideoPosnToken(thisToken,roomID))

⌨️ 快捷键说明

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