openmcu_v2_1_1/0040755000176200056700000000000010366011671013653 5ustar releasepostincropenmcu_v2_1_1/ChangeLog0100644000176200056700000000105010366011671015416 0ustar releasepostincr2006-01-16 03:43 csoutheren * filemembers.cxx: Fixed problem with crashes at end of playing files 2005-12-20 18:27 csoutheren * main.cxx: Disable sending room member lists as this code is never implemented in clients 2005-08-12 06:30 rjongbloed * .cvsignore: More ignorance 2005-06-21 07:45 rjongbloed * conference.h: Disabled video so will compile - for now. 2005-03-10 18:36 csoutheren * version.h: Incremented version 2005-03-10 18:35 csoutheren * main.cxx, main.h, version.h: Fixed compile problems with latest CVS openmcu_v2_1_1/Makefile0100644000176200056700000000337410214162564015317 0ustar releasepostincr# # Makefile # # Make file for OpenMCU # # Copyright (c) 1993-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 Portable Windows Library. # # The Initial Developer of the Original Code is Equivalence Pty. Ltd. # # Portions are Copyright (C) 1993 Free Software Foundation, Inc. # All Rights Reserved. # # Contributor(s): ______________________________________. # # $Log: Makefile,v $ # Revision 2.2 2005/03/11 00:25:24 csoutheren # Fixed problems with flags # # Revision 2.1 2004/05/27 09:58:50 csoutheren # Added new source files to Makefile # # 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 # # Revision 1.4 2002/08/05 10:10:29 robertj # Normalised Makefile usage of openh323u.mak include file, fixing odd messages. # # Revision 1.3 2001/06/28 05:56:10 rogerh # Add README to the tar sources for consistency # # Revision 1.2 2000/05/10 08:11:57 craigs # Fixed copyrights and names # # PROG = openmcu SOURCES := main.cxx audio.cxx conference.cxx filemembers.cxx custom.cxx STDCCFLAGS += -DNO_MCU_VIDEO ifndef OPENH323DIR OPENH323DIR=$(HOME)/openh323 endif include $(OPENH323DIR)/openh323u.mak openmcu_v2_1_1/ReadMe.txt0100644000176200056700000001000110022752440015531 0ustar releasepostincrNotes for OpenMCU ----------------- Roger Hardiman, 20 June 2001 1. Introduction --------------- OpenMCU is a simple Mutli Conference Unit using the H.323 protocol. It requires the OpenH323 library - see http://www.openh323.org for more information. It is known to run on Linux and FreeBSD and should run on any platform supported by OpenH323. If you run the program sucessfully on another platform them please email to openh323@openh323.org 2. Features ----------- The code contains the following features: - requires no codec hardware to operate - supports G.711, GSM MS-GSM and LPC-10 audio codecs - supports H.261 video codec - can accept multiple connections simultaneously - several different conferences can be talking place at the same time using the 'rooms' feature - display statistics on calls in progress - initiate calls from the MCU to remote endpoints - audio loopback mode echoes back your audio in a specific room. Ideal for setup of audio hardware and testing network performance. 3. Operation ------------ OpenMCU works by setting up a H.323 listener process, and then waiting for incoming connections. Whenever an incoming connection is established, it determines which conference is required via the 'rooms' feature and adds the call to that conference. You call the MCU using the format "room_name@server_name" eg using ohphone I type ohphone meeting1@mcu.myservers.com New rooms are created automatically and there is a default room for people who do not specify a room or cannot specify a room (eg NetMeeting). The default room is called room101. You hear the audio from the other users, but only see the video from the four users activly talking. 4. Command line options ----------------------- OpenMCU has the following command line options: -u --username str : Set the local endpoint name to str -g --gatekeeper host : Specify gatekeeper host. -n --no-gatekeeper : Disable gatekeeper discovery. --require-gatekeeper : Exit if gatekeeper discovery fails. -i --interface ip : Bind to a specific interface --g711frames count : Set the number G.711 frames in capabilities (default 30) --gsmframes count : Set the number GSM frames in capabilities (default 4) -t --trace : Enable trace, use multiple times for more detail -o --output : File for trace output, default is stderr --save : Save arguments in configuration file -v --video : Enable H261 video handling --videolarge : Set the video size from normal (176x144) to large (352x288). --videotxquality n : Select sent video quality,(def 9). 1(good)<=n<=31 --videofill n : Select number of updated background blocks per frame 1<=n<=99 (2 def) --videotxfps n : Maximum number of transmitted video frames per sec 1<10(def)<30 --defaultroom name : Connections without a room name will join this room (Default room is room101) --no-defaultroom : Reject connections with no room specified --disable-menu : Disable the command line menu --audio-loopback name : Users hear their own voice echo'ed back in this room (Users also hear their own voice in room 'loopback') (Use the name "*" to enable loopback in all rooms) -h --help : Display this help message Generally it is sufficient to use just the -n and -v options eg openmcu -n (audio conference unit, with no gatekeeper) openmcu -n -v (audio and video conference unit, with no gatekeeper) 5. OpenMCU menu options ----------------------- When running openMCU, the following menu options are available (unless the --disable-menu has been specified on the command line) ? : Print this help message v : report which connections are at each video corner m : make a call x : Exit immediately s : Report statistics z : Put message in log file (for debugging) When making a call, the call will be added to the default room (currently room101). ------------------------ openmcu_v2_1_1/audio.cxx0100644000176200056700000000425510022752440015476 0ustar releasepostincr/* * audio.cxx * * Audio 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: audio.cxx,v $ * 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 #include "main.h" #define MIN_HEADROOM 30 #define MAX_HEADROOM 60 AudioDelay::AudioDelay() { firstTime = TRUE; error = 0; } void AudioDelay::Restart() { firstTime = TRUE; } BOOL AudioDelay::Delay(int frameTime) { if (firstTime) { firstTime = FALSE; previousTime = PTime(); return TRUE; } // add in the new delay error += frameTime; // remove the actual delay since the last call PTime now; PTimeInterval delay = now - previousTime; error -= (int)delay.GetMilliSeconds(); previousTime = now; // if the delay is > 10 ms, then accumulate the error until next time if (error > 10) { #ifdef P_LINUX usleep(error * 1000); #else PThread::Current()->Sleep(error); #endif } //return error <= -frameTime; return FALSE; } openmcu_v2_1_1/conference.cxx0100644000176200056700000004614610124377436016524 0ustar releasepostincr/* * 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 #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(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 "<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(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::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::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()) { PString tokenToWipe = spokenList[keyIndex-videoPosnList.GetSize()]; keyIndex = FindTokensVideoPosn(tokenToWipe,roomID); } if(keyIndex != P_MAX_INDEX) videoPosnList[keyIndex] = thisToken; } processAudio: #endif PINDEX i; for (i = 0; i < memberList.GetSize(); i++) memberList.GetDataAt(i).WriteAudio(source, buffer, amount); return TRUE; } #endif void Conference::OnMemberJoining(ConferenceMember * member) { manager.OnMemberJoining(this, member); } void Conference::OnMemberLeaving(ConferenceMember * member) { manager.OnMemberLeaving(this, member); } /////////////////////////////////////////////////////////////////////////// ConferenceMember::ConferenceMember(void * _id) : id(_id) { conference = NULL; } BOOL ConferenceMember::AddToConference(Conference * _conference) { if (conference != NULL) return FALSE; conference = _conference; return TRUE; } void ConferenceMember::RemoveFromConference() { if (conference != NULL) { if (conference->RemoveMember(this)) conference->GetManager().RemoveConference(conference->GetID()); } } void ConferenceMember::AddConnection(ConferenceMember * memberToAdd) { void * newID = memberToAdd->GetID(); PTRACE(3, "Conference\tAdding " << newID << " to connection " << id); if (lock.Wait(TRUE)) { ConferenceConnection * conn = memberToAdd->CreateConnection(); memberList.insert(std::pair(newID, memberToAdd)); connectionList.insert(std::pair(newID, conn)); lock.Signal(TRUE); } } void ConferenceMember::RemoveConnection(void * idToDelete) { PTRACE(3, "Conference\tRemoving member " << idToDelete << " from connection " << id); if (lock.Wait(TRUE)) { memberList.erase(idToDelete); connectionList.erase(idToDelete); lock.Signal(TRUE); } } void ConferenceMember::SendUserInputIndication(const PString & str) { PTRACE(3, "Conference\tConnection " << id << " sending user indication " << str); if (lock.Wait()) { MemberList::iterator r; for (r = memberList.begin(); r != memberList.end(); ++r) r->second->OnReceivedUserInputIndication(str); lock.Signal(); } } void ConferenceMember::WriteAudio(const void * buffer, PINDEX amount) { if (lock.Wait()) { MemberList::iterator r; for (r = memberList.begin(); r != memberList.end(); ++r) r->second->OnExternalAudio(id, (BYTE *)buffer, amount); lock.Signal(); } } void ConferenceMember::ReadAudio(void * buffer, PINDEX amount) { // First, set the buffer to empty. memset(buffer, 0, amount); if (lock.Wait()) { // get number of channels to mix ConnectionList::iterator r; for (r = connectionList.begin(); r != connectionList.end(); ++r) r->second->ReadAndMixAudio((BYTE *)buffer, amount, (PINDEX)connectionList.size()); lock.Signal(); } } void ConferenceMember::OnExternalAudio(void * source, const void * buffer, PINDEX amount) { if (lock.Wait()) { ConnectionList::iterator r = connectionList.find(source); if (r != connectionList.end()) r->second->Write((BYTE *)buffer, amount); lock.Signal(); } } #ifndef NO_MCU_VIDEO virtual BOOL ConferenceMember::OnOutgoingVideo(void * buffer, PINDEX & amount) { } virtual BOOL ConferenceMember::OnIncomingVideo(const void * buffer, PINDEX amount) { } #endif /////////////////////////////////////////////////////////////////////////// ConferenceConnection::ConferenceConnection(void * _id) : id(_id), bufferSize(PCM_BUFFER_SIZE) { buffer = new BYTE[bufferSize]; bufferStart = bufferLen = 0; } ConferenceConnection::~ConferenceConnection() { delete[] buffer; } void ConferenceConnection::Write(const BYTE * data, PINDEX amount) { if (amount == 0) return; PWaitAndSignal mutex(audioBufferMutex); // if there is not enough room for the new data, make room PINDEX newLen = bufferLen + amount; if (newLen > bufferSize) { PINDEX toRemove = newLen - bufferSize; bufferStart = (bufferStart + toRemove) % bufferSize; bufferLen -= toRemove; } // copy data to the end of the new data, up to the end of the buffer PINDEX copyStart = (bufferStart + bufferLen) % bufferSize; if ((copyStart + amount) > bufferSize) { PINDEX toCopy = bufferSize - copyStart; memcpy(buffer + copyStart, data, toCopy); copyStart = 0; data += toCopy; amount -= toCopy; bufferLen += toCopy; } // copy the rest of the data if (amount > 0) { memcpy(buffer + copyStart, data, amount); bufferLen += amount; } } void ConferenceConnection::ReadAudio(BYTE * data, PINDEX amount) { if (amount == 0) return; PWaitAndSignal mutex(audioBufferMutex); if (bufferLen == 0) { memset(data, 0, amount); // nothing in the buffer. return silence return; } // fill output data block with silence if audiobuffer is // almost empty. if (amount > bufferLen) memset(data + bufferLen, 0, amount - bufferLen); // only copy up to the amount of data remaining PINDEX copyLeft = PMIN(amount, bufferLen); // if buffer is wrapping, get first part if ((bufferStart + copyLeft) > bufferSize) { PINDEX toCopy = bufferSize - bufferStart; memcpy(data, buffer + bufferStart, toCopy); data += toCopy; bufferLen -= toCopy; copyLeft -= toCopy; bufferStart = 0; } // get the remainder of the buffer if (copyLeft > 0) { memcpy(data, buffer + bufferStart, copyLeft); bufferLen -= copyLeft; bufferStart = (bufferStart + copyLeft) % bufferSize; } } void ConferenceConnection::ReadAndMixAudio(BYTE * data, PINDEX amount, PINDEX channels) { if (amount == 0) { PTRACE(3, "Mixer\tNo data to read"); return; } PWaitAndSignal mutex(audioBufferMutex); if (bufferLen == 0) { // nothing in the buffer to mix. return; } // only mix up to the amount of data remaining PINDEX copyLeft = PMIN(amount, bufferLen); // if buffer is wrapping, get first part if ((bufferStart + copyLeft) > bufferSize) { PINDEX toCopy = bufferSize - bufferStart; Mix(data, buffer + bufferStart, toCopy, channels); data += toCopy; bufferLen -= toCopy; copyLeft -= toCopy; bufferStart = 0; } // get the remainder of the buffer if (copyLeft > 0) { Mix(data, buffer + bufferStart, copyLeft, channels); bufferLen -= copyLeft; bufferStart = (bufferStart + copyLeft) % bufferSize; } } void ConferenceConnection::Mix(BYTE * dst, const BYTE * src, PINDEX count, PINDEX /*channels*/) { #if 0 memcpy(dst, src, count); #else PINDEX i; for (i = 0; i < count; i += 2) { int srcVal = *(short *)src; int dstVal = *(short *)dst; int newVal = dstVal; #if 0 //The loudest person gains the channel. #define mix_abs(x) ((x) >= 0 ? (x) : -(x)) if (mix_abs(newVal) > mix_abs(srcVal)) dstVal = newVal; else dstVal = srcVal; #else //Just add up all the channels. if ((newVal + srcVal) > 0x7fff) dstVal = 0x7fff; else dstVal += srcVal; #endif *(short *)dst = (short)dstVal; dst += 2; src += 2; } #endif } /////////////////////////////////////////////////////////////// MCULock::MCULock() { closing = FALSE; count = 0; } BOOL MCULock::Wait(BOOL hard) { mutex.Wait(); if (hard) return TRUE; BOOL ret = TRUE; if (!closing) count++; else ret = FALSE; mutex.Signal(); return ret; } void MCULock::Signal(BOOL hard) { if (hard) { mutex.Signal(); return; } mutex.Wait(); if (count > 0) count--; if (closing) closeSync.Signal(); mutex.Signal(); } void MCULock::WaitForClose() { mutex.Wait(); closing = TRUE; BOOL wait = count > 0; mutex.Signal(); while (wait) { closeSync.Wait(); mutex.Wait(); wait = count > 0; mutex.Signal(); } } openmcu_v2_1_1/conference.h0100644000176200056700000003573110256005741016140 0ustar releasepostincr/* * conference.h * * 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.h,v $ * Revision 2.5 2005/06/21 12:45:21 rjongbloed * Disabled video so will compile - for now. * * Revision 2.4 2005/03/11 00:25:24 csoutheren * Fixed problems with flags * * Revision 2.3 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.2 2004/03/31 03:36:38 csoutheren * Fixed problem with user indication messages * Fixed problems with room listener and unlisten * * Revision 2.1 2004/03/11 20:49:44 csoutheren * Removed warnings * * 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 * */ #ifndef _OpenMCU_CONFERENCE_H #define _OpenMCU_CONFERENCE_H #ifdef _WIN32 #pragma warning(disable:4786) #pragma warning(disable:4100) #endif #include #include #include #include class OpenMCUH323Connection; #define NO_MCU_VIDEO //////////////////////////////////////////////////// #ifndef NO_MCU_VIDEO class VideoBuffer : public PObject { PCLASSINFO(VideoBuffer, PObject); public: VideoBuffer(); ~VideoBuffer(); void WriteAll( BYTE * ptr, PINDEX amount); //For single stream option void Write( BYTE * ptr, PINDEX amount, PINDEX posn); void Read(BYTE * ptr, PINDEX amount); void Clear(PINDEX posn); //Reset the buffer at the specified position void SetSize(int x, int y); // Set the vidbuffer size protected: BYTE * buffer; PINDEX videoBufferSize; ///Total number of bytes in buffer. Never gets changed. PMutex videoBufferMutex; int bufferFrameSize; int xSize, ySize; }; typedef map VideoBufferDict; #endif //////////////////////////////////////////////////// class AudioDelay : public PObject { PCLASSINFO(AudioDelay, PObject); public: AudioDelay(); virtual BOOL Delay(int time); virtual void Restart(); protected: PTime previousTime; BOOL firstTime; int error; }; class VideoDelay : public AudioDelay { PCLASSINFO(VideoDelay, AudioDelay); public: BOOL Delay(int time); }; //////////////////////////////////////////////////// class MCULock : public PObject { PCLASSINFO(MCULock, PObject); public: MCULock(); BOOL Wait(BOOL hard = FALSE); void Signal(BOOL hard = FALSE); void WaitForClose(); protected: PMutex mutex; BOOL closing; int count; PSyncPoint closeSync; }; //////////////////////////////////////////////////// class Conference; /** * this class describes a connection between a conference member and a conference * each conference member has one instance of class for every other member of the conference */ class ConferenceConnection : public PObject { PCLASSINFO(ConferenceConnection, PObject); public: ConferenceConnection(void * _id); ~ConferenceConnection(); void * GetID() const { return id; } #ifdef _WIN32 #pragma warning(push) #pragma warning(disable:4311) #endif virtual PString GetName() const { return PString(PString::Unsigned, (unsigned)id); } #ifdef _WIN32 #pragma warning(pop) #endif virtual void OnUserInputIndication(const PString &) { } void WriteAudio(void * source, const void * buffer, PINDEX amount); void Write(const BYTE * ptr, PINDEX amount); void ReadAudio(BYTE * ptr, PINDEX amount); void ReadAndMixAudio(BYTE * ptr, PINDEX amount, PINDEX channels); protected: Conference * conference; void * id; void Mix(BYTE * dst, const BYTE * src, PINDEX count, PINDEX channels); BYTE * buffer; PINDEX bufferLen; ///Number of bytes unread in the buffer. PINDEX bufferStart; ///Current position in the buffer. PINDEX bufferSize; ///Total number of bytes in buffer. Never gets changed. PMutex audioBufferMutex; #ifndef NO_MCU_VIDEO BOOL hasVideo; IncomingVideo * incomingVideo; OutgoingVideo * outgoingVideo; #endif }; //////////////////////////////////////////////////// /** * this class describes a member of a conference */ class ConferenceManager; class ConferenceMember : public PObject { PCLASSINFO(ConferenceMember, PObject); public: /** * create a new conference member. The single parameter is an "id" (usually a pointer) * that can used to identify this member unambiguously */ ConferenceMember(void * id); /** * used to add a conference member to a conference. This is not done in the constructor * as some conference members have non-trivial startup requirements */ virtual BOOL AddToConference(Conference * conference); /** * used to remove a conference member from a conference. This is not done in the destructor * as some conference members have non-trivial shutdown requirements */ virtual void RemoveFromConference(); /** * If this returns TRUE, the conference member will be visible in all publically displayed * conference lists. It will always be visible in the console displays */ virtual BOOL Visible() const { return TRUE; } /** * return the conference member ID */ void * GetID() const { return id; } #ifdef _WIN32 #pragma warning(push) #pragma warning(disable:4311) #endif /** * return the name of the the conference member */ virtual PString GetName() const { return PString(PString::Unsigned, (unsigned)id); } #ifdef _WIN32 #pragma warning(pop) #endif /** * return the conference this member belongs to */ Conference * GetConference() { return conference; } /** * add a new connection for the specified member to this member to the internal list of connections */ virtual void AddConnection(ConferenceMember * newMember); /** * remove any connections belong to the specified ID from the internal list of connections */ virtual void RemoveConnection(void * id); /** * This is called when the conference member want to send a user input indication to the the conference. * By default, this routines calls OnReceivedUserInputIndication for all of the other conference members */ virtual void SendUserInputIndication(const PString & str); /** * this virtual function is called when the conference sends a user input indication to the endpoint * the conference */ virtual void OnReceivedUserInputIndication(const PString & str) { } /** * Called when the conference member want to send audio data to the cofnerence */ virtual void WriteAudio(const void * buffer, PINDEX amount); /** * Called when the conference member wants to read a block of audio from the conference */ virtual void ReadAudio(void * buffer, PINDEX amount); /** * Called when another conference member wants to send audio to the endpoint * By default, the audio is added to the queue for the specified member * so it can be retreived by a later call to OnIncomingAudio */ virtual void OnExternalAudio(void * id, const void * buffer, PINDEX amount); /* * Used to create a conference connection for this member */ virtual ConferenceConnection * CreateConnection() = 0; void WaitForClose() { lock.WaitForClose(); } protected: typedef std::map ConnectionList; typedef std::map MemberList; Conference * conference; void * id; MCULock lock; ConnectionList connectionList; MemberList memberList; }; //////////////////////////////////////////////////// /** * this class describes a conference or "room" */ class Conference : public PObject { PCLASSINFO(Conference, PObject); public: typedef std::map MemberList; Conference(ConferenceManager & manager, const OpalGloballyUniqueID & _guid, const PString & _number, const PString & _name); ~Conference(); PMutex & GetMutex() { return memberListMutex; } ConferenceManager & GetManager() { return manager; } /** * add the specified member to the conference */ void AddMember(ConferenceMember * member); /** * remove the specifed member from the conference. * Note that this function does not actually delete the conference member * as sometimes a conference member needs to remove itself from a conference * * @return if TRUE, the conference is now empty */ BOOL RemoveMember(ConferenceMember * member); MemberList & GetMemberList() { return memberList; } virtual PString GetName() const { return name; } virtual PString GetNumber() const { return number; } OpalGloballyUniqueID GetID() const { return guid; } virtual BOOL IsVisible() const { return TRUE; } virtual void OnMemberJoining(ConferenceMember *); virtual void OnMemberLeaving(ConferenceMember *); protected: ConferenceManager & manager; PMutex memberListMutex; MemberList memberList; OpalGloballyUniqueID guid; PString number; PString name; }; //////////////////////////////////////////////////// typedef std::map ConferenceList; class ConferenceManager : public PObject { PCLASSINFO(ConferenceManager, PObject); public: ConferenceManager(); /** * Make a new conference with the specified conference ID, number and name */ Conference * MakeConference( const OpalGloballyUniqueID & conferenceID, const PString & number, const PString & name ); /** * Make a new conference with the specified number and name, and use a new conference ID */ Conference * MakeConference( const PString & number, const PString & name ); /** * return true if a conference with the specified ID exists */ BOOL HasConference( const OpalGloballyUniqueID & conferenceID ); /** * return true if a conference with the specified number exists */ BOOL HasConference( const PString & number ); /** * Remove and delete the specified conference */ void RemoveConference(const OpalGloballyUniqueID & confId); /** * Remove the specified member from the specified conference. * The member will will deleted, and if the conference is empty after the removal, * it is deleted too */ void RemoveMember(const OpalGloballyUniqueID & confId, ConferenceMember * toRemove); PMutex & GetConferenceListMutex() { return conferenceListMutex; } ConferenceList & GetConferenceList() { return conferenceList; } virtual void OnCreateConference(Conference *) { } virtual void OnDestroyConference(Conference *) { } virtual void OnMemberJoining(Conference *, ConferenceMember *) { } virtual void OnMemberLeaving(Conference *, ConferenceMember *) { } protected: virtual Conference * CreateConference(const OpalGloballyUniqueID & _guid, const PString & _number, const PString & _name); PMutex conferenceListMutex; ConferenceList conferenceList; }; #ifndef NO_MCU_VIDEO //////////////////////////////////////////////////// /** OutGoingVideo describes the data leaving the computer, and then sent by TCP/IP methods to the remote computer. OutGoingVideo is the connection/channel which connects the codec and the connection class, for the transport of data. */ class OutgoingVideo : public PVideoChannel { PCLASSINFO(OutgoingVideo, PVideoChannel); public: OutgoingVideo(H323EndPoint & ep, OpenMCUH323Connection & conn, int framesPerSec, BOOL videoLarge); ~OutgoingVideo(); BOOL Close(); /** uses over ride of Read function in the PChannel class. */ BOOL Read(void * buffer, PINDEX amount); void SetRenderFrameSize(int /*_width*/, int /*_height*/) {PTRACE(3,"OutgoingVideo Set size");} BOOL Redraw(const BYTE * /*frame*/) { return TRUE; } BOOL IsOpen() const { return !closed; } BOOL IsGrabberOpen() { return TRUE; } PINDEX GetGrabWidth() { return (videoLarge ? 352 : 176); } /**Return the height of the currently selected grabbing device. */ PINDEX GetGrabHeight() { return (videoLarge ? 288 : 144 ); } protected: H323EndPoint & ep; OpenMCUH323Connection & conn; PMutex videoChanMutex; BOOL videoLarge; VideoDelay delay; int msBetweenFrames; BOOL closed; }; //////////////////////////////////////////////////// /** IncomingVideo describes the data entering the computer, which is placed in the video buffer. */ class IncomingVideo : public PVideoChannel { PCLASSINFO(IncomingVideo, PVideoChannel); public: IncomingVideo(MyH323EndPoint & ep, OpenMCUH323Connection & conn); ~IncomingVideo(); BOOL Write(const void * buffer, PINDEX amount); BOOL Close(); void SetRenderFrameSize(int _width, int _height); BOOL Redraw(const BYTE * frame) { return Write(frame,0); } BOOL IsOpen() const { return !closed; } PINDEX GetGrabWidth() { PTRACE(3,"incomingvideo get grab width"); return width; } /**Return the height of the currently selected grabbing device. */ PINDEX GetGrabHeight() { return height; } protected: MyH323EndPoint & ep; OpenMCUH323Connection & conn; PMutex videoChanMutex; PINDEX width; PINDEX height; PINDEX frameSize; VideoDelay delay; BOOL closed; }; #endif #endif openmcu_v2_1_1/connecting.wav0100644000176200056700000002467210055037447016535 0ustar releasepostincrRIFF)WAVEfmt @@fact~)data)gggggggggggggggggggggggg[[[S[SSS[SSSSS[[[[ggg[[SSSSSSSSSMMMMMMSS[[gggg[[[[[[SSSSMMMMMMSS[ggg[[[[[SSSSSSMMMMMMS[[gg[[[[[[[SSSSSSSSSSSS[[gggggg[[[[[[SSSSSSSSS[ggggg[[[S[SMSMMMSS[gg[[[gg[gg[g[[[[[SMMMMMS[gg[SSMMSSM[[[ggg[SMME>EMESSEIA8448>AIgSA:0--246M;[A4-+-.00)'*./8纰M4+'%%)//%"+4M8-%'0EӶE/$%/Aɫ6("".SA/'+IɯE)"*>E-$!8E-!#-AŬE/%2ɬ>-##.EŬ>-% 8g6+#&4[4)"'[>-("!+E>+$ 6S.($! '6ӰM/% /Ũ0($! "'2[4(  .ӫ8*&$"#(0[g6*# ,箣<+'%$$(/M<-&!!+SI/*(%$&->ӴE0)$" !(>6-*'%&+8g[8-)&$"%/簩I4.+(&)/AۺM6.+*(%'4۲M84/*)*0A[<40/-*)/MSE<2.-/8IžSA<:84.-0A۾SA866<<<>AM[MMMM[[[SSSMMMMSSSS[ggg[[[[ggg[[[[SS[[[g[[SSMMSS[[ggggggg[[[SS[[[ggggg[ggggggggggggggggggggg[ggg[[ggggggggggggggggggggggggggggggggg[S[MM羾M>MgE>E[S[[MM[[S[gMI[[SS[S[g[[gSMSg[SSg[g[IISgSMM[g[g[MS[gg[Sgg[[[gg[g[S[[ME[ME[MESMIS[S[SMggg[[gSEM[SMM[MMg[S[[[[gMEM[[g[g[MMSgSMEI[g[MMMS[MEIgSMM[gSSMS[[SMM[[MMMS[gSMMSSS[gg[[SSSgS[[gSIS[SS[[[g[SIM[gS[gggg[SMSg[I<:ASgMEM[[IAEMSMA:8Sż[AESggMA<::<<<:88<<<60/26:>>EEA<4/../268848SM۸M66>ISMA8.(%'.>MA2/M88簪A008AIIA4+# %.:>66ɤA(.ɧ/*.AA0)$ (/:8:筚,(ŴS2,)((*+.(&0Ş$#ۡ2/>Ų[4,)((*++()AM"+00EE/*(&(*,+*8-!&E>4<۸:-)&&*+,+0竛<%%6g::[>/)&&*+--6ͩ6%&8[<AͶ<-$"%*/4AӬE+(4۰AE[g4*#%(.2<[:+->ɴ[IMͺE4(%&*/6MŬS0,4[MIg<.&'(/6EӶA//>ۼSEIӾM4)''-4>羬6/4MɾIE[ɾ>.(&*0<ůA22>MAIžM2)((/6SͶ[84<[SEE[<,)'-2EӸA88M[ME[A.*&).<縪E:-&"%+AūS>AS[MEI<-&!")>MAESSEAEg>.% &8M>ASgE>MgS>66Ažg6(-ۧ[AI[[A606EI."%AMM[gE8/08Sg8'"6[gI:004Ag>+!"4gI<426>S[<,# &8[E<646>IS[I6*#"*ESA:680($&0ۮgI<88:>EIME8-&$)<[E<8:<>EII>4*%&/[MA<::<>AEE:/)&*8ӯMA><<<>AEA8.('.E[IA><<:<>A>4+')2g[MEA<:80*(,<Ӵ[MIA:68EA8.*+2IͺI<448>A<4,)+4Sɸ[A866/+,2E۾[A88:>AA>82-,/>E:88<<><<4-*+6[źS<688888<842:602۸MA<844:ESI<-&"(0Eɯ[E>8646.'$(/>۲SA:864<6.*+2A[ɲM<4/./6<<:4.,06/..06886204>Mͺ[>6/..06886446ASӾgA80./06888668ASɾM>6202668:<<842468<>AEEM[[žSE><<<>AIM[[[SSSMMS[ž[MIEEMMS[[g[SSIIEEMM[ggg[SSMEIEEIEMS[[[SSMMIMMMSSSS[g[[SSSSSSSS[[[[[[[[[gg[[gg[g[g[[[g[[gg[gggggg[[[[[[[g[[ggg[g[[[[gggggggg[g[[[[[[[gggggggg[[gggggggggggggggggggggg[[gg[gggggggggggggggggggggggggggggggggggggggggggg[gg[gggggg[gggggggggggggggggggggggggg[[[[[[gggggg[SMMS[gg[[ggg[SMMg[g[[SMS[ggg[[[[[[[[gg[[[[[[gggggggggg[[[[SSSSMMMMS[gggɺ>MEM[g[[EgMAS[E[gMEgMSggSgggg[ggggg[g[[[[[[[[g[[[[[[gS[g[[gSg[g[S[[[ggggg[[[[[[gggg[[gggg[gg[g[ggg[[[[g[[[[SMSSMMIEAAEA>EEEEMS[[SMIEA>>A<<<>88<8<<:888<<>EIgźgSSI>>>:8:8868<<>SŶgg[g[[[gg[SE<:64444646:6020.24446A[ŰMIEEISgSIAA><::84/.--/6M<:8:>gž[SMIEA>>>840.-,.A[A>EAESɼMSSS[Sg[[SMSMA<64/-2>S;[MMS[g[[[MA<60.--.06>M[gSSMMS[g[[SMIEA<84226:AMgg[SS[[[[SSME>840048>I[g[[gg[[SSIA<8400468642268>ESɾg[[[[[[[[[[[[[SSME><864246:642248>E[[[[SSSSSMSSSSSSMMEA>:644448>E[g[[SSSMMMMMMSSSSMMIE><864448<86448<>E[ɼgggg[[[MMMEEAEA><<84../0>ɾ[IEMͼSMA<>EII[I<6/+(&))/M[S[MMggA>AEEM[gS<882//.,,+0Eɰ[g[[ɾ[SA842/+*+->۰SgSgžMI>862/**+0[ESSgɸIEA:2/-))/IIM[[ͺE>A80.+(*6[ES[S>AAES[[[S[[SSE<4-,)(0S[I[[ɺ[AAAESg[S[[SMA:4-,))<粨SMgSAEAM[[S[[[MMA80-+)-Eɯ[E[SEEEMg[[S[[[SE>6-++)8۶ggEMžMIEE[gSMMS[[[E<2-+).Iɮ[E>MSɾ[IAAM[EAAEMMI<40+)4S[>>IMź[MAAMžM><<<<<:60.6IŶAAE>E[žMEEM[SE<8866644><:44:EIM<4004[ɾM>60/.//06>M͸[>2--,.:ME:640488<>ESżS>4042:MgŸI<82466I[ӾI><86:<>ISMI[[źgMA><>EI[SIA<<>>AEIAAIM[ż[IA>><<>A>>AEM۾[MA<>>>SžżSEE>:><:>>>ES͸I><<<:::<:>ES[E>>>:88:>AEM[[[MEA><>>AM[ž[SIIMMS[g[SMIEEEIMMS[gg[[SSSMMMMMMMMMMS[ggg[[[SSSMMMIEEAAEM[g[SIEEAA><::<8866:A[[[[[[[g[SMEA><86668ASg[[[[[[[[SIE><:86468A[ɾ[SSSS[[g[SIE><:86668>S[[[[[[g[SIA><:88646<:86668>Mg[S[ggSMA><<<:888><<::<>AMžg[SS[[gg[SIEA>>>>>AAEMSg[SSMIEEEEEEIMSS[ggg[[SSSSSSSSS[[[[gg[ggg[ggg[[[SSSS[[[[[[[[[[[ggggg[[[[[[gg[[[[[[[[[[[[[ggggggg[[[[[[[[[[ggggggggggggggggggggggggggggopenmcu_v2_1_1/custom.cxx0100644000176200056700000000613610055037447015720 0ustar releasepostincr/* * custom.cxx * * Application source file for OpenMCU * * Customisable application configuration for OEMs. * * Copyright (C) 2004 Post Increment * * $Log: custom.cxx,v $ * Revision 2.1 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 * */ #ifdef RC_INVOKED #include #else #include #include "custom.h" #endif #include "version.h" //////////////////////////////////////////////////// // // Variables required for PHTTPServiceProcess // //////////////////////////////////////////////////// #define PRODUCT_NAME_TEXT "OpenMCU" #define EXE_NAME_TEXT "openmcu" #define MANUFACTURER_TEXT "Post Increment" #define COPYRIGHT_HOLDER MANUFACTURER_TEXT #ifndef GIF_NAME #define GIF_NAME EXE_NAME_TEXT ".gif" #define GIF_WIDTH 380 #define GIF_HEIGHT 101 #endif #define EMAIL "info@postincrement.com" #define HOME_PAGE "http://www.postincrement.com" #define PRODUCT_NAME_HTML PRODUCT_NAME_TEXT #ifdef RC_INVOKED #define AlphaCode alpha #define BetaCode beta #define ReleaseCode pl #define MkStr2(s) #s #define MkStr(s) MkStr2(s) #if BUILD_NUMBER==0 #define VERSION_STRING \ MkStr(MAJOR_VERSION) "." MkStr(MINOR_VERSION) #else #define VERSION_STRING \ MkStr(MAJOR_VERSION) "." MkStr(MINOR_VERSION) MkStr(BUILD_TYPE) MkStr(BUILD_NUMBER) #endif VS_VERSION_INFO VERSIONINFO #define alpha 1 #define beta 2 #define pl 3 FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_TYPE,BUILD_NUMBER PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_TYPE,BUILD_NUMBER #undef alpha #undef beta #undef pl FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0 #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "0c0904b0" BEGIN VALUE "CompanyName", MANUFACTURER_TEXT "\0" VALUE "FileDescription", PRODUCT_NAME_TEXT "\0" VALUE "FileVersion", VERSION_STRING "\0" VALUE "InternalName", EXE_NAME_TEXT "\0" VALUE "LegalCopyright", "Copyright " COPYRIGHT_HOLDER " 2001\0" VALUE "OriginalFilename", EXE_NAME_TEXT ".exe\0" VALUE "ProductName", PRODUCT_NAME_TEXT "\0" VALUE "ProductVersion", VERSION_STRING "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0xc09, 1200 END END #else PHTTPServiceProcess::Info ProductInfo = { PRODUCT_NAME_TEXT, MANUFACTURER_TEXT, MAJOR_VERSION, MINOR_VERSION, PProcess::BUILD_TYPE, BUILD_NUMBER, __TIME__ __DATE__, {{ 0 }}, { NULL }, 0, {{ 0 }}, // Only relevent for commercial apps HOME_PAGE, EMAIL, PRODUCT_NAME_HTML, NULL, // GIF HTML, use calculated from below GIF_NAME, GIF_WIDTH, GIF_HEIGHT, MANUFACTURER_TEXT, HOME_PAGE, EMAIL }; #endif // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/custom.h0100644000176200056700000000110110055037447015330 0ustar releasepostincr/* * custom.h * * Application header file for OpenMCU * * Customisable application configuration for OEMs. * * Copyright (C) 2004 Post Increment * * $Log: custom.h,v $ * Revision 2.1 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 * */ #include extern PHTTPServiceProcess::Info ProductInfo; // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/entering.wav0100644000176200056700000003015410055037447016211 0ustar releasepostincrRIFFd0WAVEfmt @>data@0>=l=[z  \ kjRr2|1 s D y ZH;;c # ] I a.( 8 !  39 r y X .=l] # oA ]m) M .  i[A'Nl$ cb `='+NEF * )d^0> 1% w_bd  `M- eE& 43 O ^IvGIV= i< fHV = 01b#< L U{`{Gi " +f~Aw* * DDpu "   QP{. !3|> |'MP2c {6Q rDK  dO U8| X +!RjK - : c+w=G a~a `MSx-k ~ 8j{e(5k[!7 hrwpV  " 2:V( k^& h `q)   @d_[+{@^R cbH  &EC$O BH Du/|   hcDl0 t O WZ2QR kf j c^u o L;/R5#'&3 G5  ^U91 ( (RN2#5 +1 NzIv Dn OJ<  F.n,] 8<  >=SH A^UA 6y4h9G #W ch= }3 #(6,K Mt.K+ #K <E=nie GDKc EucB+ / t408w  ( \ ` L$tYV t n RCJ%Vd 3 g* s ( Y A~pT f 4Lz2/ 0 @zO[ N  E T RK90q > 4u w% p Q 5oh [<U$k& L <;:(da & h  y0*80I e 0 wK-{3- $t]b1?M H ! 7  [B3   LU<@  E :z L@4G;&+0l l*V&k_i _ r ?Ia $C $ mPEcy{2 T {Qw{T*k> 7]o +{8S[ Ehs!ei){,4C!U,|k Ym ?WU$W&^*~3Sn6D!I|/Jkrxn]rE!/7e9b"/a+v3NAen7 h'_PL9P$m/Ho5i+k!A>Jxn{*zMjI44Y/9GM|+Yd:OfLM+`o [m vi>o>!=a}Zu-je1/ 6+Rk!31Q>7"y8"'"LlH4-fMYS*!00J.+wKe;6s8T#LUT=[V)TE^kU6qu*?\X^)`b-TR1K'ici XVIbG{t *FZL"^owz B$jXTQ4E6WNE|.VFL9.%PR"Q2l4& 1 \knZ  O&rbchuA.3()rV WSK v^ j.`K:D K (uk Us0e-s 1 |;:29Jf:/ eBK|R@ exP 2 ,.=m "[1:q3  4u yhk m -yo C0XrN)v U "y5 w n n}6* U h%O AS u 9;j}Q cN>%G 4&z Z@XU"%  }o\hV} D Tsh J agI=I P:a4gxYO j[q n +q? 0i CP p qP  o tnnB9,0 V ! 4 &mq( S; J F !rn4/ T GBt=PTY(ol)lN`c1 -Vn {Jd |* wm sAh Lnj-)aq<L20NV0 H|o XMlvo  I{4 ]6 1`Z) 4 c?K g} ) OJJ_  CS t{^  }2W 8d> 8 6 WkX^& | lj[< TJg)9 ]9 X x O V u^, #u   rp8M_  +{ <AQF 6T Sm+ : . -86 BV RFa. @l!< ,o~#6 m s dKr Z ")pB>c  b%BZ% f|;>p$o d*zrH .YB \>  >{A6u{ | NW MR gf_ u N#,Bx_: P [>[M"yOd\[ G |~V_Ic L ' Gq<u_rn N &ywm Z  q'MVd,'P  l)   Ch\g 6X #  E@Z&g  6 d`uC%_fP*%v  b$ 3 5*_Qxkc{ Q "{ K -)"gy?=.  mmg8 1)x%"<3 4Jd'f`s HoKc#xZrO 4I.G8p .?M2X;%_xtAid'wJv8N2[D[GBXCsqtb=)MUssFt$%{HV L<l A  :FgOoPP4L ~_J ?3dS#7KOcP/f?&\!m=l\,IBaPmxp MmJ R/,Ca?(w|*|%lrrC&_R3XqT$3/ss NA/)T Q0&{QBFV6. 22Zm)g45OSfw;=}%@SVhsz\Byw*5j>bux;ck?Y9/B8V6&#d^oy75'MB[kxb IXdsAk$<\}>lkY?~:zoTU#J:w5*>j4b0;5 >Y$*PiS2[AXT]Fumd3Y z;~;`!l*u,~>(KA#] qd[ELx^ L;$cRH'L3/_u*U[rZ%t7Rl?40[8SxP((]-ur uFf{={+N_g@`IP.T\r}C5&B4[zc7c%} !d=e# /jkS6,8c_,JWO@G 6tq%Q>2m'+V tt=+5>&w-D9'S..l;MTe+QS9nft< ( w7Xd"RZYE3f: #>=Xbp Ed?$  Z!wWj@(jD PMB9W,CCyc#YU-ctS9!)rK3N(/=o)"E\ 'Mv !h]DRh A]{>Xg 3<`3M'{Dm$<$|$Oz=@GS-h`c *J'>7N<% jkn,rH<(D11z'^<~&x,;J)Z$o5aR.=_ ~~ oU6H<Ns;eM<`3COuc$kz? KPv !MGXMx;a>5~KC$vFIWTC MTpOU=m '@X~aVfU $k~5+U?l|;\K WYi|2]GS|:\ *Az7)]XDhzgqK=%h=FI/ 9xILN2|")F^8?SS yA=csIaa?'\:f\\%$;"unqObK B]h2 17N\R%E}"Ijr 6JLOh0c^b=(8nozoD^Dx7T.pNUj=tO 6B+z,Uzi"UTfU:E nJ(#0 L d C* 1pwk'K 32!NPZ>( rDlzP5KcC~ { KIDfitOPo*6 3\  no> gIy ?6 (l^BpDW\p2?21|~"Xl}' _"]9& }%Yg>zG76 p4a(>Q P6il|/JoeK2kK(hxL4<'n1t`;k.openmcu_v2_1_1/filemembers.cxx0100644000176200056700000001205310362665251016674 0ustar releasepostincr/* * filemembers.cxx * * Various file-based Members for OpenMCU * * Copyright (C) 2003 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 Post Increment * * 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: filemembers.cxx,v $ * Revision 2.2 2006/01/16 09:43:05 csoutheren * Fixed problem with crashes at end of playing files * * Revision 2.1 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 * */ #include #include "conference.h" #include "filemembers.h" ConferenceSoundCardMember::ConferenceSoundCardMember() #ifdef _WIN32 #pragma warning(push) #pragma warning(disable:4355) #endif : ConferenceMember(this) #ifdef _WIN32 #pragma warning(pop) #endif { // open the default audio device PString deviceName = PSoundChannel::GetDefaultDevice(PSoundChannel::Player); soundDevice.Open(deviceName, PSoundChannel::Player, 1, 8000, 16); // start a thread to read from the conference and write to default audio device if (!soundDevice.IsOpen()) { thread = NULL; } else { running = TRUE; thread = PThread::Create(PCREATE_NOTIFIER(Thread), 0, PThread::AutoDeleteThread); } } ConferenceSoundCardMember::~ConferenceSoundCardMember() { Unlisten(); } void ConferenceSoundCardMember::Unlisten() { if (conference->RemoveMember(this)) conference->GetManager().RemoveConference(conference->GetID()); if ((thread != NULL) && running) { running = FALSE; thread->WaitForTermination(); thread = NULL; } } void ConferenceSoundCardMember::Thread(PThread &, INT) { AudioDelay audioDelay; PBYTEArray pcmData(480); soundDevice.SetBuffers(480, 3); while (running) { // read a block of data ReadAudio(pcmData.GetPointer(), pcmData.GetSize()); // write the data to the sound card if (soundDevice.IsOpen()) soundDevice.Write(pcmData.GetPointer(), pcmData.GetSize()); audioDelay.Delay(pcmData.GetSize() / 16); } ConferenceManager & mgr = conference->GetManager(); mgr.RemoveMember(conference->GetID(), this); } /////////////////////////////////////////////////////////////////////////// ConferenceFileMember::ConferenceFileMember(const PFilePath & _fn, PFile::OpenMode _mode) #ifdef _WIN32 #pragma warning(push) #pragma warning(disable:4355) #endif : ConferenceMember((void *)this), filename(_fn), mode(_mode) #ifdef _WIN32 #pragma warning(pop) #endif { // open the default audio device if (!file.Open(filename, mode)) { PTRACE(1, "Cannot open WAV file " << filename); return; } PTRACE(1, "Playing WAV file " << filename); running = TRUE; if (mode == PFile::WriteOnly) thread = PThread::Create(PCREATE_NOTIFIER(WriteThread), 0, PThread::AutoDeleteThread); else thread = PThread::Create(PCREATE_NOTIFIER(ReadThread), 0, PThread::AutoDeleteThread); } ConferenceFileMember::~ConferenceFileMember() { Unlisten(); } void ConferenceFileMember::Unlisten() { if (conference->RemoveMember(this)) conference->GetManager().RemoveConference(conference->GetID()); if ((thread != NULL) && running) { running = FALSE; thread->WaitForTermination(); thread = NULL; } } void ConferenceFileMember::WriteThread(PThread &, INT) { PBYTEArray pcmData(480); AudioDelay audioDelay; while (running) { // read a block of data ReadAudio(pcmData.GetPointer(), pcmData.GetSize()); // write to the file if (file.IsOpen()) file.Write(pcmData.GetPointer(), pcmData.GetSize()); // and delay audioDelay.Delay(pcmData.GetSize() / 16); } ConferenceManager & mgr = conference->GetManager(); mgr.RemoveMember(conference->GetID(), this); } void ConferenceFileMember::ReadThread(PThread &, INT) { PBYTEArray pcmData(480); AudioDelay audioDelay; while (running) { if (!file.IsOpen()) break; // read a block of data from the file if (!file.Read(pcmData.GetPointer(), pcmData.GetSize())) break; // read a block of data WriteAudio(pcmData.GetPointer(), pcmData.GetSize()); // and delay audioDelay.Delay(pcmData.GetSize() / 16); } ConferenceManager & mgr = conference->GetManager(); mgr.RemoveMember(conference->GetID(), this); } openmcu_v2_1_1/filemembers.h0100644000176200056700000000627410055037447016330 0ustar releasepostincr/* * filemembers.h * * Various file-based listeners for OpenMCU * * Copyright (C) 2003 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 Post Increment * * 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: filemembers.h,v $ * Revision 2.1 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 * */ #ifndef _OpenMCU_FILEMEMBERS_H #define _OpenMCU_FILEMEMBERS_H #include "conference.h" #include class ConferenceSoundCardMember : public ConferenceMember { PCLASSINFO(ConferenceSoundCardMember, ConferenceMember); public: ConferenceSoundCardMember(); ~ConferenceSoundCardMember(); void Unlisten(); virtual ConferenceConnection * CreateConnection() { return new ConferenceConnection(this); } virtual PString GetName() const { return "listener"; } virtual BOOL Visible() const { return FALSE; } void OnReceivedUserInputIndication(const PString & str) { cout << "Received user input indication " << str << endl; } PDECLARE_NOTIFIER(PThread, ConferenceSoundCardMember, Thread); protected: BOOL running; PSoundChannel soundDevice; PThread * thread; }; class ConferenceFileMember : public ConferenceMember { PCLASSINFO(ConferenceFileMember, ConferenceMember); public: ConferenceFileMember(const PFilePath & _fn, PFile::OpenMode mode); ~ConferenceFileMember(); void Unlisten(); virtual ConferenceConnection * CreateConnection() { return new ConferenceConnection(this); } virtual PString GetName() const { return "listener"; } virtual BOOL Visible() const { return FALSE; } void OnReceivedUserInputIndication(const PString & str) { cout << "Received user input indication " << str << endl; } PDECLARE_NOTIFIER(PThread, ConferenceFileMember, ReadThread); PDECLARE_NOTIFIER(PThread, ConferenceFileMember, WriteThread); protected: PFilePath filename; PFile::OpenMode mode; OpalWAVFile file; BOOL running; PThread * thread; }; class ConferenceFilePlayer : public ConferenceFileMember { PCLASSINFO(ConferenceFilePlayer, ConferenceFileMember); public: ConferenceFilePlayer(); void Unlisten(); PDECLARE_NOTIFIER(PThread, ConferenceFilePlayer, Thread); }; #endif openmcu_v2_1_1/leaving.wav0100644000176200056700000003202210055037447016017 0ustar releasepostincrRIFF 4WAVEfmt @>data3tl .29G  !\FLK 6 P !T 8 - * 1bT_ ]#,V / Rs?e 0G _pqr  1#  =&  *,\o = M]JQ _ KmD  [u 2B Bkc  g1O_ ! SKR `XE  + X ! L( cV j4U A] ^a Kn RM k(i pn fo' V=28   ,H(C {ta1-}l /!a p  y` X|W , T U zXQ<-. BhLNLG  nE] O(pI% NG% y 2YhR2b 1'" :t2b2C b<i  K!!` oy _Z 8N". aD\ 51G~ d` # D= YB hc ze3*r5 Gk6  I.? f: Y  XFgY \F=c~;% Cx- JY)7 iLoG \x(2{~b[ 2'`UZ k_{k g C /N`'pf H dI5b]U`D L d qSBr,AJ  7$  aV2w gr: M e3Qv2{?Vh  9;3l8&=  w A~ {)T o ,b/ e 13y < ]t  K1 8 s/ i! L.tt" J =&7 ( 0rI < B= 6f LZ  jR% vp l o^@ 8 nWPl ; .xYY] @  'kz  shO,6, " 9 Y uwQJi g pY  57* 7 {$ 2 9La  SV(S vPpk k ] M@ ~  [^[   +m ? w "` %{#qt W@%  d5TJ"KW G 7Iw q3 Z {I&,G G ) ,B y $&>  f R)m 7Ir!r>} 4 g8 Y 0+VQ 6jMX)  r[V GLw s5 i S ZvUe @ f 0 iwQn g  jK5 S|{X jf $h  !LSO*3 U mknc( @/sh,{ [O0~T( g v  ZsA  ZG>] L_qg' v tv9i^f \,0A|)t M) Am N|n7TC`]_f@Q[l rf.Z7d7qijjv/1e Zm8#jzSq,o?yW(LhE;vNkU'K4 mf8TQ` ?=Zs+gw`pwoSo\Y5Q b1EuTBX:"@ZZllv^l":Devrz9A"a-PWzn$_hRj~wq)GDsa.DIi8O7 ,)2s3i>n2@Gc[ {5A8HTFL[1u*R0-GK&N^UK8Q-F+ yx !K0fV9d<5sCB"UiYl%d /[oU"SJ=3"q(7 | ]m3oj ?G`:TN .Y  Lw&U ,GjYX, I(D8/D p _u SF $X-1 Wy NH,w bhO c AM 1 ;,EF r [l#i l?A6"t WwE "x/|9d2m.r ww 5 , Sesx)k j  q*dUag [h+pJx 5} ZU {ed %}o JoRR>7 5 O:W, rd]"%N*ESh u7: 3 bHA 8Y z#mn ($)5 Q9_ ~wLq^ v ._F3fR  vGas\Qp}2|DF|` c kX  Y  !?7'} 7SBm0o uji+dSUW=Y^'chi p` T= =D, K M 5%On P ?,N`" 9.Fc(y f? `Qeusv f 0xc0P y\AEy;j\t 'H7 P % 7_ b ;7/ ;@HEEo 4pg2]#MFc   <Wak[ujv > jh)a  zr18: ?d% :+I'n_ B Z ~Z,6Q'4'b@Qw gm%C | Fu.u` vuX ' }@gF! !#<^Y_&S i e.fz a % ^ukTnJN5R88 ?9MLFM$b q/ v` Y |-hb{5M _6 MlU roSaTW } __R ? M N 6 0{ n+ ]Ih 1k  xL'5w  !#;D+ )4# P , +7_ 6 K&,|n  xX~> , $L*tw[ % < r:   :$>UaU$ } 52EhN 1 O#=sC O t#td(:3u f na|hG T ) j:QHa|pW  h >8Sq c $L cs_SK,K j 0:S855! ! y 6y]3C1 } ])X[U * NO2 k g(0( ri@gh  DJT7 F1 n Iu"V v? ,=2 ]LG V;~ { cF= ye2< H tJT8k  d 3 +Wa*DUmO$E=5 WU{~ Y 4Ed 2 U /}eEx;l"s   F  o[oynEe+`*hY?9$ v5r'0gje o !aU=O^QdYCE-1)V^ =,_%|$1W Gy:[NP}-V;u8~K"Qs'6h1u:"nyu(Y@E?bpe>/0{jQ|1" -t+tkF$[{?uee[acP T*PVW wl__:b `?,`b)\-;_8'kFvU)q4-M#1+f:@1:s!vdMDZ^z~& E(-GNQU{1RpSiC `n4;0w[W @x )2gXgv+L&Znv)'d^eX|<5:9~ _ojCXB<q!"UC[;!z_MkG<f@3EQT!CC)nkF7Vz  {{C6OszG|>uEvFYDx.e*}C$RZm5SaPZ5pJ`M~k\-;D:Vo&x rx?-%/CY$A TGy rBd@`c"<]^ [5 F:G 37q`8KP"0tH\L[.!~XS/r]Jk:Z@I-)TM S+EwWPBx&b"r= -$ o3MFy_b-oEI;N`YAve|Jf\`4P{aE*zb,e"[ |VHV7rtPE ,j5t7U79Q-.s>U wc}l( (XncHXI w`QS/K+Yt[{Bhmc){ ;& >;j{{HfQMNV?8L D5n) `EMqh3I$vR&&#M.y!x 0mF!'tXvxl-#`#:kG@?kaA $\[- nq#g @ ;to:Fw~\wUQRKY_`bOC*TsNxQiIo(` V&\8kh !`I@Ad4Iy1-'IVEl*=soWFkz\ K;-2$*.qdZ ATH.L Lx2"U"EO;R)cQ[^,#icoU. *nCGd}D{P\#8mBXaf[}[ ci^v{fRfi}L?Z3fM=K'gT~xq> zGGtzA]l.id5#1O+&tc{7 #include #include "version.h" #include "main.h" PCREATE_PROCESS(OpenMCU); const WORD DefaultHTTPPort = 1420; static const char LogLevelKey[] = "Log Level"; static const char UserNameKey[] = "Username"; static const char PasswordKey[] = "Password"; static const char HttpPortKey[] = "HTTP Port"; static const char LocalUserNameKey[] = "Local User Name"; static const char GatekeeperPasswordKey[] = "Gatekeeper Password"; static const char GatekeeperModeKey[] = "Gatekeeper Mode"; static const char GatekeeperKey[] = "Gatekeeper"; static const char DefaultRoomKey[] = "Default room"; static const char DisableCodecsKey[] = "Disable codecs"; static const char CallLogFilenameKey[] = "Call log filename"; static const char InterfaceKey[] = "Interface"; static const char ConnectingWAVFileKey[] = "Connecting WAV File"; static const char EnteringWAVFileKey[] = "Entering WAV File"; static const char LeavingWAVFileKey[] = "Leaving WAV File"; #if P_SSL static const char HTTPCertificateFileKey[] = "HTTP Certificate"; #endif static const char DefaultCallLogFilename[] = "mcu_log.txt"; static const char DefaultRoom[] = "room101"; static const char DefaultConnectingWAVFile[] = "connecting.wav"; static const char DefaultEnteringWAVFile[] = "entering.wav"; static const char DefaultLeavingWAVFile[] = "leaving.wav"; static const char * GKModeLabels[] = { "No gatekeeper", "Find gatekeeper", "Use gatekeeper", }; enum { Gatekeeper_None, Gatekeeper_Find, Gatekeeper_Explicit }; #define GKMODE_LABEL_COUNT (sizeof(GKModeLabels)/sizeof(char *)) #define new PNEW /////////////////////////////////////////////////////////////// class MainStatusPage : public PServiceHTTPString { PCLASSINFO(MainStatusPage, PServiceHTTPString); public: MainStatusPage(OpenMCU & app, PHTTPAuthority & auth); virtual BOOL Post( PHTTPRequest & request, const PStringToString &, PHTML & msg ); private: OpenMCU & app; }; /////////////////////////////////////////////////////////////// OpenMCU::OpenMCU() : OpenMCUProcessAncestor(ProductInfo) { endpoint = NULL; } void OpenMCU::Main() { Suspend(); } BOOL OpenMCU::OnStart() { // change to the default directory to the one containing the executable PDirectory exeDir = GetFile().GetDirectory(); #if defined(_WIN32) && defined(_DEBUG) // Special check to aid in using DevStudio for debugging. if (exeDir.Find("\\Debug\\") != P_MAX_INDEX) exeDir = exeDir.GetParent(); #endif exeDir.Change(); httpNameSpace.AddResource(new PHTTPDirectory("data", "data")); httpNameSpace.AddResource(new PServiceHTTPDirectory("html", "html")); endpoint = new MyH323EndPoint(); return PHTTPServiceProcess::OnStart(); } void OpenMCU::OnStop() { delete endpoint; endpoint = NULL; PHTTPServiceProcess::OnStop(); } void OpenMCU::OnControl() { // This function get called when the Control menu item is selected in the // tray icon mode of the service. PStringStream url; url << "http://"; PString host = PIPSocket::GetHostName(); PIPSocket::Address addr; if (PIPSocket::GetHostAddress(host, addr)) url << host; else url << "localhost"; url << ':' << DefaultHTTPPort; PURL::OpenBrowser(url); } BOOL OpenMCU::Initialise(const char * initMsg) { PConfig cfg("Parameters"); // Set log level as early as possible SetLogLevel((PSystemLog::Level)cfg.GetInteger(LogLevelKey, GetLogLevel())); #if PTRACING if (GetLogLevel() >= PSystemLog::Warning) PTrace::SetLevel(GetLogLevel()-PSystemLog::Warning); else PTrace::SetLevel(0); PTrace::ClearOptions(PTrace::Timestamp); PTrace::SetOptions(PTrace::DateAndTime); #endif // Get the HTTP basic authentication info PString adminUserName = cfg.GetString(UserNameKey); PString adminPassword = PHTTPPasswordField::Decrypt(cfg.GetString(PasswordKey)); PHTTPSimpleAuth authority(GetName(), adminUserName, adminPassword); // Create the parameters URL page, and start adding fields to it PConfigPage * rsrc = new PConfigPage(*this, "Parameters", "Parameters", authority); // HTTP authentication username/password rsrc->Add(new PHTTPStringField(UserNameKey, 25, adminUserName)); rsrc->Add(new PHTTPPasswordField(PasswordKey, 25, adminPassword)); // Log level for messages rsrc->Add(new PHTTPIntegerField(LogLevelKey, PSystemLog::Fatal, PSystemLog::NumLogLevels-1, GetLogLevel(), "1=Fatal only, 2=Errors, 3=Warnings, 4=Info, 5=Debug")); #if P_SSL // SSL certificate file. PString certificateFile = cfg.GetString(HTTPCertificateFileKey, "server.pem"); rsrc->Add(new PHTTPStringField(HTTPCertificateFileKey, 25, certificateFile)); if (!SetServerCertificate(certificateFile, TRUE)) { PSYSTEMLOG(Fatal, "BMAC\tCould not load certificate \"" << certificateFile << '"'); return FALSE; } #endif // HTTP Port number to use. WORD httpPort = (WORD)cfg.GetInteger(HttpPortKey, DefaultHTTPPort); rsrc->Add(new PHTTPIntegerField(HttpPortKey, 1, 32767, httpPort)); endpoint->Initialise(cfg, rsrc); // get default "room" (conference) name defaultRoomName = cfg.GetString(DefaultRoomKey, DefaultRoom); rsrc->Add(new PHTTPStringField(DefaultRoomKey, 25, defaultRoomName)); // get WAV file played to a user when they enter a conference connectingWAVFile = cfg.GetString(ConnectingWAVFileKey, DefaultConnectingWAVFile); rsrc->Add(new PHTTPStringField(ConnectingWAVFileKey, 50, connectingWAVFile)); // get WAV file played to a conference when a new user enters enteringWAVFile = cfg.GetString(EnteringWAVFileKey, DefaultEnteringWAVFile); rsrc->Add(new PHTTPStringField(EnteringWAVFileKey, 50, enteringWAVFile)); // get WAV file played to a conference when a new user enters leavingWAVFile = cfg.GetString(LeavingWAVFileKey, DefaultLeavingWAVFile); rsrc->Add(new PHTTPStringField(LeavingWAVFileKey, 50, leavingWAVFile)); // default log file name logFilename = cfg.GetString(CallLogFilenameKey, DefaultCallLogFilename); rsrc->Add(new PHTTPStringField(CallLogFilenameKey, 50, logFilename)); // see if audio loopback is required //audioLoopbackRoom = args.GetOptionString("audio-loopback"); // get singleStream flag //endpoint.singleStream = args.HasOption("single-stream"); #ifndef NO_MCU_VIDEO // If videoLarge was specified endpoint.videoLarge = args.HasOption("videolarge"); if (args.HasOption('v')) { //Add capability to allow the reception of video. // this is the only way I know of at present to transmit // CIF size video - pez // Do not allow CIF video if size is medium if (endpoint.videoLarge) endpoint.SetCapability(0, 1, new H323_H261Capability(0, 4, FALSE, FALSE, 6217)); // CIF endpoint.SetCapability(0, 1, new H323_H261Capability(2, 0, FALSE, FALSE, 6217)); // QCIF } #endif // Finished the resource to add, generate HTML for it and add to name space PServiceHTML html("System Parameters"); rsrc->BuildHTML(html); httpNameSpace.AddResource(rsrc, PHTTPSpace::Overwrite); // Create the status page httpNameSpace.AddResource(new MainStatusPage(*this, authority), PHTTPSpace::Overwrite); // Add log file links if (!systemLogFileName && systemLogFileName != "-") { httpNameSpace.AddResource(new PHTTPFile("logfile.txt", systemLogFileName, authority)); httpNameSpace.AddResource(new PHTTPTailFile("tail_logfile", systemLogFileName, authority)); } // create the home page static const char welcomeHtml[] = "welcome.html"; if (PFile::Exists(welcomeHtml)) httpNameSpace.AddResource(new PServiceHTTPFile(welcomeHtml, TRUE), PHTTPSpace::Overwrite); else { PHTML html; html << PHTML::Title("Welcome to OpenMCU") << PHTML::Body() << GetPageGraphic() << PHTML::Paragraph() << "
" << PHTML::HotLink("Parameters") << "Parameters" << PHTML::HotLink() << PHTML::Paragraph() << PHTML::HotLink("Status") << "Status" << PHTML::HotLink() << PHTML::Paragraph(); if (!systemLogFileName && systemLogFileName != "-") html << PHTML::HotLink("logfile.txt") << "Full Log File" << PHTML::HotLink() << PHTML::BreakLine() << PHTML::HotLink("tail_logfile") << "Tail Log File" << PHTML::HotLink() << PHTML::Paragraph(); html << PHTML::HRule() << GetCopyrightText() << PHTML::Body(); httpNameSpace.AddResource(new PServiceHTTPString("welcome.html", html), PHTTPSpace::Overwrite); } // create monitoring page PString monitorText = "" "Current Proxies: \n"; httpNameSpace.AddResource(new PServiceHTTPString("monitor.txt", monitorText, "text/plain", authority), PHTTPSpace::Overwrite); // set up the HTTP port for listening & start the first HTTP thread if (ListenForHTTP(httpPort)) PSYSTEMLOG(Info, "Opened master socket for HTTP: " << httpListeningSocket->GetPort()); else { PSYSTEMLOG(Fatal, "Cannot run without HTTP port: " << httpListeningSocket->GetErrorText()); return FALSE; } PSYSTEMLOG(Info, "Service " << GetName() << ' ' << initMsg); return TRUE; } void OpenMCU::OnConfigChanged() { } PString OpenMCU::GetNewRoomNumber() { static PAtomicInteger number = 100; return PString(PString::Unsigned, ++number); } void OpenMCU::LogMessage(const PString & str) { static PMutex logMutex; static PTextFile logFile; PTime now; PString msg = now.AsString("dd/MM/yyyy") & str; logMutex.Wait(); if (!logFile.IsOpen()) { logFile.Open(logFilename, PFile::ReadWrite); logFile.SetPosition(0, PFile::End); } logFile.WriteLine(msg); logFile.Close(); logMutex.Signal(); } ////////////////////////////////////////////////////////////////////////////////////////////// void MyConferenceManager::OnMemberJoining(Conference * conf, ConferenceMember * member) { if (!PIsDescendant(member, ConferenceFileMember)) conf->AddMember(new ConferenceFileMember(OpenMCU::Current().GetEnteringWAVFile(), PFile::ReadOnly)); } void MyConferenceManager::OnMemberLeaving(Conference * conf, ConferenceMember * member) { if (!PIsDescendant(member, ConferenceFileMember)) conf->AddMember(new ConferenceFileMember(OpenMCU::Current().GetLeavingWAVFile(), PFile::ReadOnly)); } ////////////////////////////////////////////////////////////////////////////////////////////// void SpliceMacro(PString & text, const PString & token, const PString & value) { PRegularExpression RegEx("?", PRegularExpression::Extended|PRegularExpression::IgnoreCase); PINDEX pos, len; while (text.FindRegEx(RegEx, pos, len)) text.Splice(value, pos, len); } PCREATE_SERVICE_MACRO_BLOCK(RoomStatus,P_EMPTY,P_EMPTY,block) { return OpenMCU::Current().GetEndpoint().GetRoomStatus(block); } MainStatusPage::MainStatusPage(OpenMCU & _app, PHTTPAuthority & auth) : PServiceHTTPString("Status", "", "text/html; charset=UTF-8", auth), app(_app) { PHTML html; html << PHTML::Title("OpenH323 MCU Status") << "\n" << PHTML::Body() << app.GetPageGraphic() << PHTML::Paragraph() << "
" //<< PHTML::Form("POST") << PHTML::TableStart("border=1") << PHTML::TableRow() << PHTML::TableHeader() << " Room Name " << PHTML::TableHeader() << " Room Members " << PHTML::TableHeader() << "" << PHTML::TableRow() << PHTML::TableData() << "" << PHTML::TableData() << "" << "" << PHTML::TableEnd() << PHTML::Paragraph() //<< PHTML::Form() << PHTML::HRule() << app.GetCopyrightText() << PHTML::Body(); string = html; } BOOL MainStatusPage::Post(PHTTPRequest & request, const PStringToString & data, PHTML & msg) { /* PTRACE(2, "VGGK\tClear call POST received " << data); msg << PHTML::Title() << "Accepted Control Command" << PHTML::Body() << PHTML::Heading(1) << "Accepted Control Command" << PHTML::Heading(1); PWaitAndSignal m(app.endpointMutex); std::vector::iterator r; for (r = app.endpointList.begin(); r != app.endpointList.end(); ++r) { if ((*r)->OnPostControl(data, msg)) msg << PHTML::Heading(2) << "No calls or endpoints!" << PHTML::Heading(2); PServiceHTML::ProcessMacros(request, msg, "html/status.html", PServiceHTML::LoadFromFile|PServiceHTML::NoSignatureForFile); } msg << PHTML::Paragraph() << PHTML::HotLink(request.url.AsString()) << "Reload page" << PHTML::HotLink() << "    " << PHTML::HotLink("/") << "Home page" << PHTML::HotLink(); */ return TRUE; } /////////////////////////////////////////////////////////////// MyH323EndPoint::MyH323EndPoint() { #if 0 terminalType = e_MCUWithAudioMP; #ifndef NO_MCU_VIDEO terminalType = e_MCUWithAVMP; #endif conferenceListener = NULL; #endif } void MyH323EndPoint::Initialise(PConfig & cfg, PConfigPage * rsrc) { // Local alias name for H.323 endpoint SetLocalUserName(cfg.GetString(LocalUserNameKey, "OpenH323 MCU v" + OpenMCU::Current().GetVersion())); // Gatekeeper mode PStringArray labels(GKMODE_LABEL_COUNT, GKModeLabels); PINDEX idx = labels.GetStringsIndex(cfg.GetString(GatekeeperModeKey, labels[0])); PINDEX gkMode = (idx == P_MAX_INDEX) ? 0 : idx; rsrc->Add(new PHTTPRadioField(GatekeeperModeKey, labels, gkMode)); // Gatekeeper password PString gkName = cfg.GetString(GatekeeperKey); // Gatekeeper password PString gkPassword = PHTTPPasswordField::Decrypt(cfg.GetString(GatekeeperPasswordKey)); SetGatekeeperPassword(gkPassword); // start the H.323 listeners PString defaultInterface = "*:1720"; H323TransportAddressArray interfaces; PINDEX arraySize = cfg.GetInteger(PString(InterfaceKey) + " Array Size"); if (arraySize == 0) StartListener(defaultInterface); else { for (int i = 0; i < arraySize; i++) interfaces.Append(new H323TransportAddress(cfg.GetString(psprintf("%s %u", InterfaceKey, i+1), ""))); StartListeners(interfaces); } rsrc->Add(new PHTTPFieldArray(new PHTTPStringField(cfg.GetDefaultSection() + "\\" + InterfaceKey, InterfaceKey, 20, defaultInterface), FALSE)); if (listeners.IsEmpty()) { PSYSTEMLOG(Fatal, "Main\tCould not open H.323 Listener"); } /* if (args.GetOptionString('q').IsEmpty()) { endpoint.behind_masq = FALSE; } else { endpoint.masqAddressPtr = new PIPSocket::Address(args.GetOptionString('q')); endpoint.behind_masq = TRUE; cout << "Masquerading as address " << *(endpoint.masqAddressPtr) << endl; } */ AddAllCapabilities(0, 0, "*"); // disable codecs as required PString disableCodecs = cfg.GetString(DisableCodecsKey); rsrc->Add(new PHTTPStringField(DisableCodecsKey, 50, disableCodecs)); if (!disableCodecs.IsEmpty()) { PStringArray toRemove = disableCodecs.Tokenise(' ', FALSE); capabilities.Remove(toRemove); } #ifndef NO_MCU_VIDEO EnableVideoReception(args.HasOption('v')); int videoTxQual = 10; if (args.HasOption("videotxquality")) videoTxQual = args.GetOptionString("videotxquality").AsInteger(); endpoint.videoTxQuality = PMAX(1, PMIN(31, videoTxQual)); int videoF = 2; if (args.HasOption("videofill")) videoF = args.GetOptionString("videofill").AsInteger(); endpoint.videoFill = PMAX(1, PMIN(99, videoF)); int videoFPS = 10; if (args.HasOption("videotxfps")) videoFPS = args.GetOptionString("videotxfps").AsInteger(); endpoint.videoFramesPS = PMAX(1,PMIN(30,videoFPS)); int videoBitRate = 0; //disable setting videoBitRate. if (args.HasOption("videobitrate")) { videoBitRate = args.GetOptionString("videobitrate").AsInteger(); videoBitRate = 1024 * PMAX(16, PMIN(2048, videoBitRate)); } endpoint.videoBitRate = videoBitRate; if (args.HasOption('v')) { #if H323_AVCODEC PTRACE(3, "Video bitrate for ffmpeg h263 is " << videoBitRate); if (endpoint.videoLarge) endpoint.SetCapability(0, 1, new H323_FFH263Capability(0, 0, 1, 0, 0, videoBitRate, videoFPS)); endpoint.SetCapability(0, 1, new H323_FFH263Capability(0, 1, 0, 0, 0, videoBitRate, videoFPS)); #endif #if H323_VICH263 PTRACE(3, "Video bitrate for vic h263 is " << videoBitRate); if (endpoint.videoLarge) endpoint.SetCapability(0, 1, new H323_H263Capability(0, 0, 1, 0, 0, videoBitRate, videoFPS)); endpoint.SetCapability(0, 1, new H323_H263Capability(0, 1, 0, 0, 0, videoBitRate, videoFPS)); #endif } #endif /*End of test on NO_MCU_VIDEO */ AddAllUserInputCapabilities(0, 2); switch (gkMode) { default: case Gatekeeper_None: break; case Gatekeeper_Find: if (!DiscoverGatekeeper(new H323TransportUDP(*this))) PSYSTEMLOG(Error, "No gatekeeper found"); break; case Gatekeeper_Explicit: if (!SetGatekeeper(gkName, new H323TransportUDP(*this))) PSYSTEMLOG(Error, "Error registering with gatekeeper at \"" << gkName << '"'); } PTRACE(2, "MCU\tCodecs (in preference order):\n" << setprecision(2) << GetCapabilities());; } H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference) { return new OpenMCUH323Connection(*this, callReference); } void MyH323EndPoint::TranslateTCPAddress(PIPSocket::Address &localAddr, const PIPSocket::Address &remoteAddr) { // if (this->behind_masq && // (remoteAddr.Byte1() != 192)) { // localAddr = *(this->masqAddressPtr); // } return; } PString MyH323EndPoint::GetRoomStatus(const PString & block) { PString substitution; PWaitAndSignal m(conferenceManager.GetConferenceListMutex()); ConferenceList & conferenceList = conferenceManager.GetConferenceList(); ConferenceList::iterator r; for (r = conferenceList.begin(); r != conferenceList.end(); ++r) { // make a copy of the repeating html chunk PString insert = block; PStringStream members; members << "" "" ""; Conference & conference = *(r->second); size_t memberListSize = 0; { PWaitAndSignal m(conference.GetMutex()); Conference::MemberList & memberList = conference.GetMemberList(); memberListSize = memberList.size(); Conference::MemberList::const_iterator s; for (s = memberList.begin(); s != memberList.end(); ++s) { if (PIsDescendant(s->second, H323Connection_ConferenceMember)) { OpenMCUH323Connection & conn = *((H323Connection_ConferenceMember *)(s->second))->GetConnection(); PTime now; PTime callStart = conn.GetConnectionStartTime(); RTP_Session * session = conn.GetSession(RTP_Session::DefaultAudioSessionID); members << "" ""; } } } members << "
" " Name " "" " Duration " "" " Codec " "" " Packets/Bytes tx " "" " Packets/Bytes rx " "
" << conn.GetRemotePartyName() << "" << (now -callStart) << " mins" << "" << conn.GetAudioTransmitCodecName() << '/' << conn.GetAudioReceiveCodecName() << "" << session->GetPacketsSent() << '/' << session->GetOctetsSent() << "" << session->GetPacketsReceived() << '/' << session->GetOctetsReceived() << "
"; SpliceMacro(insert, "RoomName", conference.GetNumber()); SpliceMacro(insert, "RoomMemberCount", PString(PString::Unsigned, (long)memberListSize)); SpliceMacro(insert, "RoomMembers", members); substitution += insert; } return substitution; } Conference * MyH323EndPoint::ConferenceRequest(H323Connection & connection, const H323SignalPDU & setupPDU, H323Connection::AnswerCallResponse & response) { const H225_Setup_UUIE & setup = setupPDU.m_h323_uu_pdu.m_h323_message_body; // get the conference ID from the incoming call OpalGloballyUniqueID conferenceID = setup.m_conferenceID; // we accept creates and joins. Invites come later :) if (setup.m_conferenceGoal.GetTag() != H225_Setup_UUIE_conferenceGoal::e_create && setup.m_conferenceGoal.GetTag() != H225_Setup_UUIE_conferenceGoal::e_join) { PTRACE(3, "MCU\tUnknown conference goal " << setup.m_conferenceGoal.GetTag()); response = H323Connection::AnswerCallDenied; return NULL; } // see if the destination address or called party matches the name of a room PString userSpecifiedRoom; BOOL userSpecifiedRoomFound = FALSE; if (setup.m_destinationAddress.GetSize() > 0) { PINDEX i; for (i = 0; !userSpecifiedRoomFound && (i < setup.m_destinationAddress.GetSize()); i++) { PString roomNumber = H323GetAliasAddressString(setup.m_destinationAddress[i++]); if (userSpecifiedRoom.IsEmpty()) userSpecifiedRoom = roomNumber; userSpecifiedRoomFound = conferenceManager.HasConference(roomNumber); } PString calledPartyNumber; if (!userSpecifiedRoomFound && setupPDU.GetQ931().GetCalledPartyNumber(calledPartyNumber) && !calledPartyNumber.IsEmpty()) { if (userSpecifiedRoom.IsEmpty()) userSpecifiedRoom = calledPartyNumber; userSpecifiedRoomFound = conferenceManager.HasConference(calledPartyNumber); } } // join an existing conference if one matches the ID if (conferenceManager.HasConference(conferenceID)) { // there is a small chance that the conference has disappeared since the HasConference above // so always use a new valid room number when creating the conference Conference * conference = conferenceManager.MakeConference(conferenceID, OpenMCU::Current().GetNewRoomNumber(), ""); PTRACE(3, "MCU\tJoining conference by ID " << conference->GetID()); response = H323Connection::AnswerCallNow; return conference; } // if we are doing a join, then we joining by ID failed if (setup.m_conferenceGoal.GetTag() == H225_Setup_UUIE_conferenceGoal::e_join) { PTRACE(3, "MCU\tJoin request for conference with unknown ID " << conferenceID); response = H323Connection::AnswerCallDeniedByInvalidCID; return NULL; } // if a room exists with the called party name, use that room even though the conference IDs don't match if (userSpecifiedRoomFound) { Conference * conference = conferenceManager.MakeConference(userSpecifiedRoom, ""); PTRACE(3, "MCU\tJoining conference " << conference->GetID() << " specified by number " << userSpecifiedRoom); response = H323Connection::AnswerCallNow; return conference; } // if no room exists with the called party name, then create a new room by that name and with the specified conference ID if (!userSpecifiedRoom.IsEmpty()) { Conference * conference = conferenceManager.MakeConference(conferenceID, userSpecifiedRoom, ""); PTRACE(3, "MCU\tCreating new conference " << conference->GetID() << " with number " << userSpecifiedRoom); response = H323Connection::AnswerCallNow; return conference; } // determine if the endpoint supports conference lists // ver 2 clients are supposed to handle conference lists, but we know NM does not // and we know OpenH323 apps prior to 1.14 cannot handle lists either BOOL canDoConferenceList = connection.GetSignallingVersion() >= 2; PString appInfo = connection.GetRemoteApplication(); if (appInfo.Find("NetMeeting") != P_MAX_INDEX) canDoConferenceList = FALSE; else if (appInfo.Find("OpenH323") != P_MAX_INDEX) { PINDEX pos = appInfo.Find("OpenH323 "); if (pos != P_MAX_INDEX) { PStringArray version = appInfo.Mid(pos+9).Tokenise('.'); if (!(version.GetSize() == 3 && version[0].AsUnsigned() >= 1 && version[1].AsUnsigned() >= 14 && version[2].AsUnsigned() >= 0)) canDoConferenceList = FALSE; } } #if 0 // if no conference, and no default room, then send the terminal a conference list if it can understand it if (canDoConferenceList) { H323SignalPDU facilityPDU; H225_Facility_UUIE & pdu = *facilityPDU.BuildFacility(connection, FALSE); pdu.RemoveOptionalField(H225_Facility_UUIE::e_callIdentifier); pdu.RemoveOptionalField(H225_Facility_UUIE::e_multipleCalls); pdu.RemoveOptionalField(H225_Facility_UUIE::e_maintainConnection); pdu.m_reason = H225_FacilityReason::e_conferenceListChoice; pdu.IncludeOptionalField(H225_Facility_UUIE::e_conferences); H225_ArrayOf_ConferenceList & conferenceList = pdu.m_conferences; conferenceList.SetSize(0); { PWaitAndSignal m(conferenceManager.GetConferenceListMutex()); ConferenceList & roomList = conferenceManager.GetConferenceList(); ConferenceList::const_iterator r; PINDEX i = 0; for (r = roomList.begin(); r != roomList.end(); ++r) { Conference & conf = *(r->second); if (conf.IsVisible()) { conferenceList.SetSize(conferenceList.GetSize()+1); H225_ConferenceList & conference = conferenceList[i++]; conference.IncludeOptionalField(H225_ConferenceList::e_conferenceID); conference.m_conferenceID = conf.GetID(); conference.IncludeOptionalField(H225_ConferenceList::e_conferenceAlias); H323SetAliasAddress(conf.GetName(), conference.m_conferenceAlias, -1); } } } PTRACE(3, "MCU\tSending conference list"); // if the PDU write fails, then close the call if (!connection.WriteSignalPDU(facilityPDU)) response = H323Connection::AnswerCallDenied; else response = H323Connection::AnswerCallDeferred; return NULL; } #endif // if there is a room to create, then join this call to that conference PString roomToCreate = OpenMCU::Current().GetDefaultRoomName(); if (!roomToCreate.IsEmpty()) { Conference * conference = conferenceManager.MakeConference(roomToCreate, ""); PTRACE(3, "MCU\tCreating/joining call to default room " << roomToCreate); response = H323Connection::AnswerCallNow; return conference; } PTRACE(3, "MCU\tRefusing call because no room specified, and no default room"); response = H323Connection::AnswerCallDenied; return NULL; } /////////////////////////////////////////////////////////////// OpenMCUH323Connection::OpenMCUH323Connection(MyH323EndPoint & _ep, unsigned callReference) : H323Connection(_ep, callReference), ep(_ep), connected(FALSE) { incomingAudio = NULL; outgoingAudio = NULL; conference = NULL; conferenceMember = NULL; sendingAllowed = TRUE; audioReceiveCodecName = audioTransmitCodecName = "none"; #ifndef NO_MCU_VIDEO incomingVideo = NULL; outgoingVideo = NULL; videoReceiveCodecName = videoTransmitCodecName = "none"; #endif connected = FALSE; cout << "Opening connection" << endl; } OpenMCUH323Connection::~OpenMCUH323Connection() { cout << "Closing connection" << endl; } void OpenMCUH323Connection::CleanUpOnCallEnd() { if (conference != NULL && conferenceMember != NULL) { LogCall(); conferenceMember->WaitForClose(); ConferenceMember * cmToDelete = conferenceMember; conferenceMember = NULL; if (conference->RemoveMember(cmToDelete)) ep.GetConferenceManager().RemoveConference(conference->GetID()); delete cmToDelete; } H323Connection::CleanUpOnCallEnd(); } H323Connection::AnswerCallResponse OpenMCUH323Connection::OnAnswerCall(const PString & /*caller*/, const H323SignalPDU & setupPDU, H323SignalPDU & /*connectPDU*/) { H323Connection::AnswerCallResponse response; conference = ep.ConferenceRequest(*this, setupPDU, response); if (conference == NULL) return response; connected = TRUE; conferenceMember = new H323Connection_ConferenceMember(this); conference->AddMember(conferenceMember); return AnswerCallNow; } BOOL OpenMCUH323Connection::OnSendSignalSetup( H323SignalPDU & callProceedingPDU) { // We are making a connection to a remote EP so add this connection to // the list of rooms and members. // We will add them to the default room as we have no method of // specifying which room our connection should join. connected = TRUE; conference = NULL; PTRACE(3, "Conference\tOutgoing connection"); return H323Connection::OnSendSignalSetup( callProceedingPDU ); } BOOL OpenMCUH323Connection::OpenAudioChannel(BOOL isEncoding, unsigned /* bufferSize */, H323AudioCodec & codec) { PString codecName= codec.GetMediaFormat(); codec.SetSilenceDetectionMode( H323AudioCodec::NoSilenceDetection ); // if (!codec.IsDescendant(H323_GSM0610Codec::Class()) && // - need to add MS-GSM here along with any other codecs // !codec.IsDescendant(H323_muLawCodec::Class())) { // cerr << "Unknown codec \"" << codecName << endl; // return FALSE; // } if ((incomingAudio == NULL) && sendingAllowed) { incomingAudio = new IncomingAudio(ep, *this); } if (outgoingAudio == NULL) { outgoingAudio = new OutgoingAudio(ep, *this); PFilePath fn = OpenMCU::Current().GetConnectingWAVFile(); PTRACE(4, "MCU\tOpening outgoing audio with file " << fn); playFile.Open(fn, PFile::ReadOnly); } if (isEncoding) { audioTransmitCodecName = codecName; codec.AttachChannel(outgoingAudio, TRUE); } else if (sendingAllowed) { audioReceiveCodecName = codecName; codec.AttachChannel(incomingAudio, TRUE); } return TRUE; } #ifndef NO_MCU_VIDEO BOOL OpenMCUH323Connection::OpenVideoChannel(BOOL isEncoding, H323VideoCodec & codec) { PStringStream codecName; codecName << codec; PWaitAndSignal mutex(videoMutex); if (isEncoding) { if (outgoingVideo == NULL) { outgoingVideo = new OutgoingVideo(ep, *this, ep.videoFramesPS, ep.videoLarge); codec.AttachChannel(outgoingVideo,TRUE); // outgoingVideo->SetFrameSize(352>>1,288>>1); } /*At last. Modularity. The video codec is told the parameters of video compresion/decompression. The only thing the video codec knows about the ouside world is how to acquire/render data, which is via the video channel, provided by the OutgoingVideo class. The codec does provide a second interface, through which ethernet packets enter (or leave) */ videoTransmitCodecName = codecName; codec.SetTxQualityLevel(ep.videoTxQuality); codec.SetBackgroundFill(ep.videoFill); if (ep.videoBitRate != 0) codec.SetMaxBitRate(ep.videoBitRate); } else { if ((incomingVideo == NULL) && sendingAllowed) incomingVideo = new IncomingVideo(ep, *this); codec.AttachChannel(incomingVideo,TRUE); videoReceiveCodecName = codecName; } return TRUE; } #endif void OpenMCUH323Connection::OnUserInputString(const PString & str) { if (conferenceMember != NULL) conferenceMember->SendUserInputIndication(str); } BOOL OpenMCUH323Connection::OnIncomingAudio(const void * buffer, PINDEX amount) { if (conferenceMember != NULL) conferenceMember->WriteAudio(buffer, amount); return TRUE; } BOOL OpenMCUH323Connection::OnOutgoingAudio(void * buffer, PINDEX amount) { if (playFile.IsOpen()) { if (!playFile.Read(buffer, amount)) { PTRACE(4, "MCU\tFinished playing file"); playFile.Close(); } else { int len = playFile.GetLastReadCount(); if (len < amount) { memset(((BYTE *)buffer)+len, 0, amount-len); } return TRUE; } } if (conferenceMember != NULL) conferenceMember->ReadAudio(buffer, amount); return TRUE; } #ifndef NO_MCU_VIDEO BOOL OpenMCUH323Connection::OnOutgoingVideo(void * buffer, PINDEX & amount) { peerList.OnOutgoingVideo(buffer, amount); } BOOL OpenMCUH323Connection::OnIncomingVideo(const void * buffer, PINDEX amount) { return conference->OnIncomingVideo(buffer, amount); } #endif /////////////////////////////////////////////////////////////// void OpenMCUH323Connection::LogCall(const BOOL accepted) { H323TransportAddress address = GetControlChannel().GetRemoteAddress(); PIPSocket::Address ip; WORD port; PStringStream stringStream, timeStream; address.GetIpAndPort(ip, port); timeStream << GetConnectionStartTime().AsString("hh:mm:ss"); stringStream << ' ' << "caller-ip:" << ip << ':' << port << ' ' << GetRemotePartyName() << " room:" << ((conference != NULL) ? conference->GetNumber() : PString()); if (accepted) { PStringStream connectionDuration; connectionDuration << setprecision(0) << setw(5) << (PTime() - GetConnectionStartTime()); OpenMCU::Current().LogMessage(timeStream + stringStream + " connection duration:" + connectionDuration); } else OpenMCU::Current().LogMessage(timeStream + " Call denied:" + stringStream); } /////////////////////////////////////////////////////////////// OutgoingAudio::OutgoingAudio(H323EndPoint & _ep, OpenMCUH323Connection & _conn) : ep(_ep), conn(_conn) { os_handle = 0; } void OutgoingAudio::CreateSilence(void * buffer, PINDEX amount) { memset(buffer, 0, amount); lastReadCount = amount; } BOOL OutgoingAudio::Read(void * buffer, PINDEX amount) { PWaitAndSignal mutexR(audioChanMutex); if (!IsOpen()) return FALSE; if (!delay.Delay(amount / 16)) { // do the read call here, by calling conn.OnOutgoingAudio(): BOOL doSilence = !conn.OnOutgoingAudio(buffer, amount); if (doSilence) CreateSilence(buffer, amount); } lastReadCount = amount; return TRUE; } BOOL OutgoingAudio::Close() { if (!IsOpen()) return FALSE; PWaitAndSignal mutexC(audioChanMutex); os_handle = -1; return TRUE; } /////////////////////////////////////////////////////////////////////////// IncomingAudio::IncomingAudio(H323EndPoint & _ep, OpenMCUH323Connection & _conn) : ep(_ep), conn(_conn) { os_handle = 0; } BOOL IncomingAudio::Write(const void * buffer, PINDEX amount) { PWaitAndSignal mutexW(audioChanMutex); if (!IsOpen()) return FALSE; if (!delay.Delay(amount / 16)) conn.OnIncomingAudio(buffer, amount); return TRUE; } BOOL IncomingAudio::Close() { if (!IsOpen()) return FALSE; PWaitAndSignal mutexA(audioChanMutex); os_handle = -1; return TRUE; } /////////////////////////////////////////////////////////////////////////// // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/main.h0100644000176200056700000004176510214162564014762 0ustar releasepostincr/* * main.h * * A simple H.323 MCU * * 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 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: main.h,v $ * Revision 2.5 2005/03/11 00:25:24 csoutheren * Fixed problems with flags * * 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/05/03 13:25:47 rjongbloed * Converted everything to be codec plug in freindly * Removed GSM and G.729 as now plug ins are "the way"! * * Revision 2.2 2004/03/31 03:36:39 csoutheren * Fixed problem with user indication messages * Fixed problems with room listener and unlisten * * Revision 2.1 2004/03/11 20:49:44 csoutheren * Removed warnings * * 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 * * Revision 1.30 2004/02/23 23:18:04 csoutheren * Fixed iLBC compile problems * Fixed NO_VIDEO compile problems * * Revision 1.29 2003/10/23 01:10:25 dereksmithies * Add fix from Alex Epshteyn to fix NO_VIDEO compiling problem. * * Revision 1.28 2003/08/05 22:47:39 dereksmithies * Apply code from Martin Andre to give single stream functionality. Thanks! * * Revision 1.27 2003/06/17 03:05:24 dereksmithies * Add H263 codec. * * Revision 1.26 2003/06/12 23:20:38 dereksmithies * Bug fix from Dave, related to delays in VideoEncoding. Thanks! * * Revision 1.25 2003/05/01 06:29:59 robertj * Added propagation of user indications from a connection to all other * connections in a room. * Minor API clean up. * * Revision 1.24 2003/02/06 02:43:49 rogerh * There is now a video buffer for each 'room', which stops people in * different rooms from seeing each other. Bug pointed out by Damien Sandras. * Will need for fix leaks and delete the video buffer when a room empties. * * Revision 1.23 2002/11/21 07:55:12 robertj * Removed redundent and incorrect function for making outgoing call. * * Revision 1.22 2002/06/14 08:05:08 dereks * Added tweak to support operation behind a NAT that forwards ports * This will use TranslateTCPAddress to change the address reported * to connections that occur from outside the 192. subnet. Thanks Sahai. * * Revision 1.21 2002/04/18 10:54:34 rogerh * Fix bug in audio mixing reportde by Bob Lindell * AudioBuffer::Read() had been optimised to do reading and mixing and * contained memset()'s which were incorrect. Clean up the code with * a proper Read() method and an optimised ReadAndMix() method. * * Revision 1.20 2001/12/02 08:17:57 rogerh * Change --audio-loopback to take a room name. Only connections to the * specified room will have audio loopback applied. The remainder of the rooms * in OpenMCU will work as normal. * Submitted by Malcolm Caldwell * I hard coded room "loopback" as a loopback room regardless of * the --audio-loopback parameter. * * Revision 1.19 2001/11/22 13:06:38 rogerh * Add --audio-loopback. Users of OpenMCU can hear their own voice echoed back * which is very handy for testing purposes. * * Revision 1.18 2001/07/23 03:55:13 rogerh * Seperate out codec names for audio and video * * Revision 1.17 2001/07/23 03:28:03 rogerh * Display the codec name in the statistics page * * Revision 1.16 2001/05/31 17:01:52 rogerh * Fixes from Dan Johansson to make video work. * Go back to using 'closed' for the Video Classes. This is needed as * the the video classes come from PVideoChannel which does not use os_handle * in its IsOpen() method. Instead, we must define our own IsOpen() method. * Also, back out the size of the image change. * Finally, add a new feature. For the first 4 connections, video from an * endpoint is displayed immediatly rather than waiting until that ep sends * some audio. (handy for endpoints with video only and with no talking) * * Revision 1.15 2001/05/31 14:29:29 rogerh * Add --disable-menu to OpenMCU * * Revision 1.14 2001/05/08 13:43:11 rogerh * Connections without a room name will now join the default room (room101) * Handy for NetMeeting users who cannot specify the room to OpenMCU. * Add --defaultroom to change the default room name. Add --no-defaultroom to * prevent use of the default room and to reject calls without a room name. * * Revision 1.13 2001/03/18 07:40:45 robertj * Fixed MSVC compatibility. * * Revision 1.12 2001/03/18 06:50:20 robertj * More changes for multiple conferences from Patrick Koorevaar. * * Revision 1.11 2001/03/05 22:36:22 robertj * Changes for logging and multiple conferences from Patrick Koorevaar. * * Revision 1.10 2001/02/09 06:09:42 robertj * Added fix for crashing on exit problem, thanks Dhomin. * * Revision 1.9 2001/02/08 07:06:37 robertj * Added 'm' command to make call, thanks Paul Zaremba. * Added ability to send CIF size images, thanks again Paul Zaremba. * * Revision 1.8 2001/01/23 02:55:05 dereks * Add user interface thread to openmcu. * tidy up the exiting process, but it is still in need of work. * * Revision 1.7 2001/01/03 03:59:26 dereks * Adjusted algorithm for selecting which corners contain which video stream. * Add gsmframes and g711frames option. Add documentation describing data flows. * * Revision 1.6 2000/12/22 08:28:23 dereks * Optimise video handling, and reduce load on mcu computer * Include noise detection routine, to determine which images are displayed when > 4 connections. * * Revision 1.5 2000/12/19 22:41:44 dereks * Add video conferencing - limited to 5 connected nodes. * Use the video channel facility now in openh323 and pwlib modules * Add simple interface to handle commands entered at the keyboard. * * Revision 1.4 2000/11/02 03:33:41 craigs * Changed to provide some sort of software timeing loop * * Revision 1.3 2000/05/25 12:06:20 robertj * Added PConfigArgs class so can save program arguments to config files. * * Revision 1.2 2000/05/10 08:11:57 craigs * Fixed copyrights and names * * Revision 1.1 2000/05/10 05:54:07 craigs * Initial version * */ #ifndef _OpenMCU_MAIN_H #define _OpenMCU_MAIN_H #ifdef _WIN32 #pragma warning(disable:4786) #endif #include #include #include #include #include #include #include "custom.h" #include "conference.h" #include "filemembers.h" #if P_SSL #include typedef PSecureHTTPServiceProcess OpenMCUProcessAncestor; #else #include typedef PHTTPServiceProcess OpenMCUProcessAncestor; #endif /** ***** Data flow. ***Audio. At any point in time, there are N nodes connected. Consequently, there are N copies of OpenMCUH323Connection class, which I will label connA, connB... connN Ther is only ever one endpoint class, which is MyH323EndPoint. There are N*(N-1) instances of audiobuffers Each connection has a dictionary, containing (N-1) instances of audiobuffers. connI has audioBuffers, labelled abA, abB, abC... (not abI) ...abM, abN >> IncomingAudio (audio data arives at the mcu) a)the audio codecs write to the IncomingAudio channel b)IncomingAudio sends data to connI c)connI writes the data to the endpoint. d)the endpoint copies the data to connA, connB.. (not connI)...connM, connN e)the connections listed in step d copy the data to the specified audiobuffer. Thus, audio data from connI is copied into abI for connA, copied into abI for connB, copied into abI for connC etc. Thus, audio data from connI is copied (N-1) times. >> OutgoingAudio (the audio encoder requests audio data to send) a)the audio codec requests data from the OutgoingAudio channel b)the OutgoingAudio channel requests data from the connI c)connI requests data from the endpoint. d)the endpoint (MyH323EndPoint::ReadAudio) method then finds the connection associated with audio codec that has requested data. - in this case connI. e)The OpenMCUH323Connection::ReadAudio method is then called for connI. f)OpenMCUH323Connection::ReadAudio combines the data in each of its audiobuffers. which is abA, abB, abC... (not abI) ...abM, abN You will notice that Outgoing audio has additional work, in that connI (at step c) could bypass the endpoint and go directly to its own audiobuffers and read the data. This code is not SMP safe, because then the memberMutex does not protect access (by outgoing audio code) to the connections. *****Video is simple. There is a video buffer in the endpoint class. When an audio packet arrives, it moves the marker for that connection up a list. If a particular connection is in the top 4 (it has spoken recently), then when a video frame arrives, the connection writes the frame to the specified section of the video buffer (eg, top left corner) When video is requested, the entire frame of data in the video buffer is copied and returned to the connection. **/ class MyConferenceManager : public ConferenceManager { public: void OnMemberJoining(Conference * conf, ConferenceMember *); void OnMemberLeaving(Conference * conf, ConferenceMember *); }; class MyH323EndPoint : public H323EndPoint { PCLASSINFO(MyH323EndPoint, H323EndPoint); public: MyH323EndPoint(); Conference * ConferenceRequest(H323Connection & connection, const H323SignalPDU & setupPDU, H323Connection::AnswerCallResponse & response); // overrides from H323EndPoint virtual H323Connection * CreateConnection(unsigned callReference); virtual void TranslateTCPAddress(PIPSocket::Address &localAddr, const PIPSocket::Address &remoteAddr); BOOL behind_masq; PIPSocket::Address *masqAddressPtr; // new functions void Initialise(PConfig & cfg, PConfigPage * rsrc); PString GetRoomStatus(const PString & block); ConferenceManager & GetConferenceManager() { return conferenceManager; } protected: #ifndef NO_MCU_VIDEO BOOL videoLarge; int videoBitRate; int videoFill; int videoFramesPS; int videoTxQuality; #endif protected: MyConferenceManager conferenceManager; //AudioDelay writeDelay; #ifndef NO_MCU_VIDEO BOOL hasVideo; StringListDict spokenListDict; //Array of 'spoken lists' used to decide the //4 user images to display (one list room) VideoBufferDict videoBufferDict; //Array of VideoBuffers,(one for each room) StringListDict videoPosnDict; //Array of 'position lists' that describe //where video is displayed in the buffer. #endif //PSyncPoint exitFlag; }; class OpenMCU : public OpenMCUProcessAncestor { PCLASSINFO(OpenMCU, OpenMCUProcessAncestor) public: OpenMCU(); void Main(); BOOL OnStart(); void OnStop(); void OnControl(); void OnConfigChanged(); BOOL Initialise(const char * initMsg); static OpenMCU & Current() { return (OpenMCU &)PProcess::Current(); } PString GetDefaultRoomName() const { return defaultRoomName; } PString GetNewRoomNumber(); void LogMessage(const PString & str); MyH323EndPoint & GetEndpoint() { return *endpoint; } PFilePath GetConnectingWAVFile() const { return connectingWAVFile; } PFilePath GetLeavingWAVFile() const { return leavingWAVFile; } PFilePath GetEnteringWAVFile() const { return enteringWAVFile; } protected: MyH323EndPoint * endpoint; long GetCodec(const PString & codecname); OpalLineInterfaceDevice * GetDevice(const PString & device); PString defaultRoomName; PFilePath logFilename; BOOL singleStream; PString audioLoopbackRoom; PFilePath connectingWAVFile; PFilePath enteringWAVFile; PFilePath leavingWAVFile; }; //////////////////////////////////////////////////// class OutgoingAudio : public PChannel { PCLASSINFO(OutgoingAudio, PChannel); public: OutgoingAudio(H323EndPoint & ep, OpenMCUH323Connection & conn); BOOL Read(void * buffer, PINDEX amount); BOOL Close(); protected: void CreateSilence(void * buffer, PINDEX amount); H323EndPoint & ep; OpenMCUH323Connection & conn; AudioDelay delay; PMutex audioChanMutex; }; //////////////////////////////////////////////////// class IncomingAudio : public PChannel { PCLASSINFO(IncomingAudio, PChannel); public: IncomingAudio(H323EndPoint & ep, OpenMCUH323Connection & conn); BOOL Write(const void * buffer, PINDEX amount); BOOL Close(); protected: H323EndPoint & ep; OpenMCUH323Connection & conn; PMutex audioChanMutex; AudioDelay delay; }; //////////////////////////////////////////////////// class H323Connection_ConferenceMember; class OpenMCUH323Connection : public H323Connection { PCLASSINFO(OpenMCUH323Connection, H323Connection); public: OpenMCUH323Connection(MyH323EndPoint &, unsigned); ~OpenMCUH323Connection(); // overrides from H323Connection BOOL OpenAudioChannel(BOOL, unsigned, H323AudioCodec & codec); void CleanUpOnCallEnd(); AnswerCallResponse OnAnswerCall(const PString &, const H323SignalPDU &, H323SignalPDU &); BOOL OnSendSignalSetup( H323SignalPDU & callProceedingPDU ); void OnUserInputString(const PString & value); // functions called for incoming and outgoing channels. // These provide a link between the audio/video channels and the endpoint. BOOL OnIncomingAudio(const void * buffer, PINDEX amount); BOOL OnOutgoingAudio(void * buffer, PINDEX amount); // functions called to put data in/out of the buffer array. BOOL ReadAudio (OpenMCUH323Connection * dest, void * buffer, PINDEX amount); BOOL WriteAudio(OpenMCUH323Connection * dest, const void * buffer, PINDEX amount); #ifndef NO_MCU_VIDEO void EnableVideoReception(BOOL isOK) { hasVideo = isOK; } BOOL OpenVideoChannel( BOOL isEncoding, H323VideoCodec & codec); BOOL OnIncomingVideo(const void * buffer, PINDEX amount); BOOL OnOutgoingVideo(void * buffer, PINDEX & amount); PString GetVideoTransmitCodecName() const { return videoTransmitCodecName; } PString GetVideoReceiveCodecName() const { return videoReceiveCodecName; } #endif PString GetAudioTransmitCodecName() const { return audioTransmitCodecName; } PString GetAudioReceiveCodecName() const { return audioReceiveCodecName; } protected: void LogCall(const BOOL accepted = TRUE); MyH323EndPoint & ep; Conference * conference; H323Connection_ConferenceMember * conferenceMember; BOOL sendingAllowed; BOOL connected; OpalWAVFile playFile; PString audioTransmitCodecName; PString audioReceiveCodecName; #ifndef NO_MCU_VIDEO PString videoTransmitCodecName; PString videoReceiveCodecName; #endif IncomingAudio * incomingAudio; OutgoingAudio * outgoingAudio; }; //////////////////////////////////////////////////// class H323Connection_ConferenceConnection : public ConferenceConnection { PCLASSINFO(H323Connection_ConferenceConnection, ConferenceConnection); public: H323Connection_ConferenceConnection(void * id) : ConferenceConnection(id) { conn = (OpenMCUH323Connection *)id; } virtual PString GetName() const { return conn->GetCallToken(); } protected: OpenMCUH323Connection * conn; }; class H323Connection_ConferenceMember : public ConferenceMember { PCLASSINFO(H323Connection_ConferenceMember, ConferenceMember); public: H323Connection_ConferenceMember(OpenMCUH323Connection * _id) : ConferenceMember((void *)_id) { conn = _id; } virtual ConferenceConnection * CreateConnection() { return new H323Connection_ConferenceConnection(conn); } virtual PString GetName() const { return conn->GetCallToken(); } void OnReceivedUserInputIndication(const PString & str) { conn->SendUserInput(str); } OpenMCUH323Connection * GetConnection() { return conn; } protected: OpenMCUH323Connection * conn; }; #endif // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/messages.mc0100644000176200056700000000051410055037447016004 0ustar releasepostincrMessageId=0x1 Language=English Fatal Error . MessageId=0x2 Language=English Error . MessageId=0x3 Language=English Warning . MessageId=0x4 Language=English Information . MessageId=0x5 Language=English Debug 1 . MessageId=0x6 Language=English Debug 2 . MessageId=0x7 Language=English Debug 3 . MessageId=0x1000 Language=English %1 . openmcu_v2_1_1/mpl-1.0.htm0100644000176200056700000004730310022752440015450 0ustar releasepostincrMozilla Public License version 1.0

MOZILLA PUBLIC LICENSE
Version 1.0


1. Definitions.

    1.1. ``Contributor'' means each entity that creates or contributes to the creation of Modifications.

    1.2. ``Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor.

    1.3. ``Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof.

    1.4. ``Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data.

    1.5. ``Executable'' means Covered Code in any form other than Source Code.

    1.6. ``Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A.

    1.7. ``Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.

    1.8. ``License'' means this document.

    1.9. ``Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is:

      A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications.

      B. Any new file that contains any part of the Original Code or previous Modifications.

    1.10. ``Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License.

    1.11. ``Source Code'' means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge.

    1.12. ``You'' means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, ``You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, ``control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity.

2. Source Code License.
    2.1. The Initial Developer Grant.
    The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:

      (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and

      (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell (``Utilize'') the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations.

    2.2. Contributor Grant.
    Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:

      (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and

      (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations.

3. Distribution Obligations.
    3.1. Application of License.
    The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5.

    3.2. Availability of Source Code.
    Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party.

    3.3. Description of Modifications.
    You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code.

    3.4. Intellectual Property Matters

      (a) Third Party Claims.
      If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled ``LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained.

      (b) Contributor APIs.
      If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file.

    3.5. Required Notices.
    You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer.

    3.6. Distribution of Executable Versions.
    You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer.

    3.7. Larger Works.
    You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code.

4. Inability to Comply Due to Statute or Regulation.

    If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.

5. Application of this License.
    This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code.
6. Versions of the License.
    6.1. New Versions.
    Netscape Communications Corporation (``Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number.

    6.2. Effect of New Versions.
    Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License.

    6.3. Derivative Works.
    If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL'' or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.)

7. DISCLAIMER OF WARRANTY.
    COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
8. TERMINATION.
    This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.
9. LIMITATION OF LIABILITY.
    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
10. U.S. GOVERNMENT END USERS.
    The Covered Code is a ``commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer software'' and ``commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein.
11. MISCELLANEOUS.
    This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License.
12. RESPONSIBILITY FOR CLAIMS.
    Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis.
EXHIBIT A.
    ``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 ______________________________________.

    The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved.

    Contributor(s): ______________________________________.''

openmcu_v2_1_1/openmcu.10100644000176200056700000001121610022752440015374 0ustar releasepostincr'\" t .\" Man page for openmcu .\" SGM 16 Jul 2001 .\" .TH openmcu 1 "16 Jul 2001" .LO 1 .SH NAME openmcu \- simple Multi Conference Unit using H.323 .SH SYNOPSIS .B openmcu [\fIoptions\fR]... .SH DESCRIPTION .PP .B openmcu is a simple Mutli Conference Unit using the H.323 protocol. It sets up a H.323 listener process, and then waits for incoming connections. Whenever an incoming connection is established, it adds that call to the specified conference or to the default one if none is specified. You specify one on your H.323 client when you call the OpenMCU server with address "room_name@server_name", where room_name is the conference you want to join. .SH OPTIONS .PP All of the command line options to .B openmcu can be specified in long form, and the most commonly used options also have single character equivalents. The long forms can also be used in the .B openmcu configuration file. .TP \fB\-u\fR, \fB\-\-username\fR \fIstr\fR Set the local endpoint name to \fIstr\fR. .TP \fB\-g\fR, \fB\-\-gatekeeper\fR \fIhost\fR Upon startup, register with only with the specified gatekeeper rather than attempting to find a gatekeeper by using UDP broadcast. .TP \fB\-n\fR, \fB\-\-no\-gatekeeper\fR Do not attempt to find a gatetkeeper upon startup using UDP broadcast. .TP \fB\-\-require\-gatekeeper\fR Exit if a gatekeeper cannot be found. .TP \fB\-i\fR, \fB\-\-interface\fR \fIIP\fR Only bind to the specified network interface address. By default, .B openmcu automatically listens for incoming calls on all TCP/IP network interfaces available on the host machine. This option is useful for running multiple copies of .B openmcu on the same multi\-homed machine, or for ensuring that only calls from the external, or internal, network will be received on a particular handset. .TP \fB\-\-g711frames\fR \fIcount\fR Set the number of G.711 frames in capabilities to \fIcount\fR. Defaults to 30. .TP \fB\-\-gsmframes\fR \fIcount\fR Set the number of GSM frames in capabilities to \fIcount\fR. Defaults to 4. .TP \fB\-t\fR, \fB\-\-trace\fR Enable debug tracing, which displays messages at run\-time to assist in debugging or problem identification. Specifying this option multiple times increases the amount of information displayed. Use the \fB\-o\fR option to write the trace information to a file rather than to stderr. .TP \fB\-o\fR, \fB\-\-output\fR \fIfilename\fR Write trace output (enabled with the \fB\-t\fR option) to the specified file rather than to stderr. .TP \fB\-\-save\fR Save arguments in configuration file. .TP \fB\-v\fR, \fB\-\-video\fR Enable H261 video handling. .TP \fB\-\-videolarge\fR Set the video size from normal (176x144) to large (352x288). .TP \fB\-\-videotxquality\fR \fIn\fR Set sent video quality to \fIn\fR, default is 9. \fIn\fR has to be between 1 (good) and 31. .TP \fB\-\-videofill\fR \fIn\fR Set the number of updated background blocks per frame to \fIn\fR, default is 2. \fIn\fR has to be between 1 and 99. .TP \fB\-\-videotxfps\fR \fIn\fR Set maximum number of transmited video frames per second to \fIn\fR, default is 10. \fIn\fR has to be between 1 and 30. .TP \fB\-\-single\-stream\fR Disable video and audio multiplexing. Only First connection is allowed to send data. .TP \fB\-\-defaultroom\fR \fIname\fR Selects the default room \fIname\fR that will be used for connections that don't specify one, default is room101. .TP \fB\-\-no\-defaultroom\fR Reject connections with no room specified. .TP \fB\-\-disable-menu\fR Disable the command line menu. .TP \fB\-h\fR, \fB\-\-help\fR Display the help message. .SH CONFIGURATION FILE .PP .B openmcu options can be set in the ohphone configuration file .B ~/.pwlib_config/openmcu.ini either by edditing this file or via the \fB\-\-save\fR option. Options must be located in the section prefixed with [Options]. The long form of any command line option specified above can be specified in the configuration file, in the format: .TP \fIoption\fR = \fIvalue\fR .SH INTERNAL MENU .PP Unless the \fB\-\-disable\-menu\fR option has been specified .B openmcu allows the user to perform various operations whilst running. These operations are accessed via single line commands which each start with a single character identifying the function. The available commands are: .TP \fB?\fR Print the menu help. .TP \fBv\fR Report which connections are at each video corner. .TP \fBm\fR Make a call, which will be added to the default room. .TP \fBx\fR Exit. .TP \fBs\fR Report statistics. .TP \fBz\fR Put message in log file (for debugging). .SH EXAMPLES .PP .TP openmcu -n Start the program without registering with a gatekeeper. .SH FILES .PP ~/.pwlib_config/openmcu.ini .SH BUGS .PP None that I know of. .SH "SEE ALSO" None openmcu_v2_1_1/openmcu.dsp0100644000176200056700000001353210056622100016021 0ustar releasepostincr# Microsoft Developer Studio Project File - Name="openmcu" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 CFG=openmcu - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "openmcu.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "openmcu.mak" CFG="openmcu - Win32 Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "openmcu - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "openmcu - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "openmcu - Win32 No Trace" (based on "Win32 (x86) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 1 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "openmcu - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /YX /FD /c # ADD CPP /nologo /MD /W4 /GR /GX /O2 /Ob2 /D "NDEBUG" /D "PTRACING" /Yu"ptlib.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0xc09 /d "NDEBUG" /d "_AFXDLL" # ADD RSC /l 0xc09 /d "NDEBUG" /d "_AFXDLL" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 # ADD LINK32 openh323.lib ptclib.lib ptlib.lib mpr.lib comdlg32.lib winspool.lib wsock32.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "openmcu - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W4 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "PTRACING" /Yu"ptlib.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0xc09 /d "_DEBUG" /d "_AFXDLL" # ADD RSC /l 0xc09 /d "_DEBUG" /d "_AFXDLL" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # ADD LINK32 openh323sd.lib ptclibd.lib ptlibsd.lib comdlg32.lib winspool.lib wsock32.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "openmcu - Win32 No Trace" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "NoTrace" # PROP BASE Intermediate_Dir "NoTrace" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "NoTrace" # PROP Intermediate_Dir "NoTrace" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W4 /GX /O2 /I "..\include" /D "NDEBUG" /Yu"ptlib.h" /FD /c # ADD CPP /nologo /MD /W4 /GR /GX /O1 /Ob2 /D "NDEBUG" /D "PASN_NOPRINTON" /D "PASN_LEANANDMEAN" /Yu"ptlib.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0xc09 /d "NDEBUG" /d "_AFXDLL" # ADD RSC /l 0xc09 /d "NDEBUG" /d "_AFXDLL" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 ptclib.lib ptlib.lib comdlg32.lib winspool.lib wsock32.lib mpr.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 openh323n.lib ptclib.lib ptlib.lib mpr.lib comdlg32.lib winspool.lib wsock32.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 # SUBTRACT LINK32 /pdb:none !ENDIF # Begin Target # Name "openmcu - Win32 Release" # Name "openmcu - Win32 Debug" # Name "openmcu - Win32 No Trace" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\audio.cxx # End Source File # Begin Source File SOURCE=.\conference.cxx # End Source File # Begin Source File SOURCE=.\custom.cxx # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\filemembers.cxx # End Source File # Begin Source File SOURCE=.\main.cxx # End Source File # Begin Source File SOURCE=.\precompile.cxx # ADD CPP /Yc"ptlib.h" # End Source File # Begin Source File SOURCE=.\video.cxx !IF "$(CFG)" == "openmcu - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "openmcu - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "openmcu - Win32 No Trace" !ENDIF # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\conference.h # End Source File # Begin Source File SOURCE=.\custom.h # End Source File # Begin Source File SOURCE=.\filemembers.h # End Source File # Begin Source File SOURCE=.\main.h # End Source File # Begin Source File SOURCE=.\version.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project openmcu_v2_1_1/openmcu.dsw0100644000176200056700000000077410022752440016040 0ustar releasepostincrMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "OpenMCU"=.\openmcu.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### openmcu_v2_1_1/openmcu.ico0100644000176200056700000000207610055037447016023 0ustar releasepostincr 0& V( @?<80 0    0 8<?????'t3t9t<d>? openmcu_v2_1_1/precompile.cxx0100644000176200056700000000140510022752440016526 0ustar releasepostincr/* * precompile.cxx * * PWLib application source file for Dump PDU * * Precompiled header generation file. * * Copyright 1999 Equivalence * * $Log: precompile.cxx,v $ * 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 * * Revision 1.1 2000/05/11 09:54:02 robertj * Win32 compilation * * Revision 1.1 1999/08/08 10:05:40 robertj * Added PDU dump program. * * Revision 1.2 1999/01/26 06:35:08 robertj * Fixed $LOG$ variable in template files * */ #include // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/server.pem0100644000176200056700000000306310055037447015667 0ustar releasepostincr-----BEGIN CERTIFICATE----- MIIB2DCCAUGgAwIBAgIBADANBgkqhkiG9w0BAQQFADAyMRcwFQYDVQQDFA5PcGVu TUNVQHJhcGlkbzEXMBUGA1UEChMOUG9zdCBJbmNyZW1lbnQwHhcNMDQwNTI1MDQz NjQwWhcNMDkwNTI0MDQzNjQwWjAyMRcwFQYDVQQDFA5PcGVuTUNVQHJhcGlkbzEX MBUGA1UEChMOUG9zdCBJbmNyZW1lbnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ AoGBAMzVWsejwSsiEC4/m5Bh8Crle97P+VzY0NFpeM+M55B5l9VEdC+1qS2XWqk0 1/6uYqiVWf8cUJTk2NSLIaOHhpmyhak59hdiTwGL2CmYt/knp+1GvFhdreDXWd2j HrfTK0rzOslPAYvVOFdCng9sLB0qX2MMR6Ogzqo8fYMwhGsTAgMBAAEwDQYJKoZI hvcNAQEEBQADgYEAhioAnSjw85l1dZIWnPx16KpxWVLuZ+qjNTBzpn8ylQvdKIIv FaI7KQXe+ZngiCmBJ4Kyy93hFxkeaccaXn9PkRb6BYqKa71C0tLQ3DVoQRZIOlUw 5CNlEfxOsAbuptQnPhzw+UImcdPmicah781H5XBWPfkV5QCkvxqgte2mjsU= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDM1VrHo8ErIhAuP5uQYfAq5Xvez/lc2NDRaXjPjOeQeZfVRHQv taktl1qpNNf+rmKolVn/HFCU5NjUiyGjh4aZsoWpOfYXYk8Bi9gpmLf5J6ftRrxY Xa3g11ndox630ytK8zrJTwGL1ThXQp4PbCwdKl9jDEejoM6qPH2DMIRrEwIDAQAB AoGAcmHuKK+8Lg7+hCUHBPB8AihWLM1sjbmRmm9QhG5F3XrZG8H3M7E5APmVKgoV V+Yft853DCvOn+bPYpkzNrN2qJs5UnoYeQZ5BqGxH5n9WMfrSiTmSXFmkHFdpSrR JR51i+T5EXexzgRnsjuo53DOqESsoGnV1n6lAVIhwuTNIcECQQDzhuj4rRF9ZASG CKwvJIQOV58nJuWR11pOz3wD4VMvgvPixojb7uRi69UhK6zUwkqwsdGCteiOHvET o/BvPuRhAkEA11MZoOw301+zds+rckkH88xl4J/yGG1pPs3zSryZgQxRlyjAHm/o bC4d+qwGLJHDgqyolUGe1l01j0PEDXSD8wJAfLzw3le/6qttib4tfCRHJBWLpwFM e+yEDHRIwLAM7Pw1skYhWg4+m9DSpZ/6cixnF6StfTdyPEHrGDVT9ZeQYQJAfKj5 r3bSoydGyURVp+asGfN+D9vJ12aQhfHKJrylylaNbgwDnht/3hGc/aFWObtyC1dW ioLhKI3yEi1Tdc69DQJANfS8Kq4jJ18m6ucZ/dEeHUqBdhfRSsZWWsrXWe2dBZ5I CnBF2sqzR4MGxORSrsL0d3GTopz+mWKIxTEeCIIYlg== -----END RSA PRIVATE KEY----- openmcu_v2_1_1/version.h0100644000176200056700000000210510214164262015501 0ustar releasepostincr/* * version.h * * Version number header file for OpenMCU conferencing server * * Copyright (c) 1993-2000 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 Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): ______________________________________. * * */ #ifndef _OpenMCU_VERSION_H #define _OpenMCU_VERSION_H #define MAJOR_VERSION 2 #define MINOR_VERSION 1 #define BUILD_TYPE ReleaseCode #define BUILD_NUMBER 1 #endif // _OpenMCU_VERSION_H // End of File /////////////////////////////////////////////////////////////// openmcu_v2_1_1/video.cxx0100644000176200056700000003521310030021026015465 0ustar releasepostincr/* * video.cxx * * Video 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: video.cxx,v $ * Revision 2.2 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.1 2004/03/11 20:49:44 csoutheren * Removed warnings * * 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 #ifdef _WIN32 #pragma warning(disable:4786) #endif #include "main.h" #ifndef NO_MCU_VIDEO VideoBuffer::VideoBuffer() : xSize(176), ySize(144) { buffer = NULL; SetSize( xSize, ySize ); } VideoBuffer::~VideoBuffer() { delete[] buffer; } void VideoBuffer::WriteAll(BYTE * data, PINDEX amount) { if (amount == 0) return; PWaitAndSignal mutex(videoBufferMutex); BYTE *yFirst, *ySecond, *u, *v, *srcYFirst, *srcYSecond, *srcU, *srcV; int srcFrameSize = (amount<<1)/3; int srcXSize = (srcFrameSize == (176 * 144) ? 176 : 352 ); int srcYSize = (srcFrameSize == (176 * 144) ? 144 : 288 ); yFirst = buffer; u= buffer + bufferFrameSize; v= buffer + bufferFrameSize + (bufferFrameSize >> 2); srcYFirst = data; srcYSecond = srcYFirst + (xSize < srcXSize ? srcXSize << 1 : srcXSize); srcU = data + srcFrameSize; srcV = data + srcFrameSize + (srcFrameSize >> 2); ySecond = yFirst + (xSize < srcXSize ? xSize : xSize << 1); // added down here so that any changes to // yFirst are taken into account - pez // Special case, can fit 'in' images perfectly inside 'out' images if ( xSize == srcXSize ) { // just copy the whole buffer memcpy(buffer, data, amount); } else if ( xSize == 176 && srcXSize == 352 ) { // Copy 1 pixel out of 2 int src_step = 3 * srcXSize; int step = xSize; int srcuv_step = (srcXSize >> 1); int uv_step = 0; for(int i=0; i> 1); for(int i=0; i> 1)) = *srcU; u++; if (j%2) srcU++; *v = *srcV; *(v + (xSize >> 1)) = *srcV; v++; if (j%2) srcV++; } srcYFirst += src_step; srcYSecond += src_step; yFirst += step; ySecond += step; srcU += srcuv_step; srcV += srcuv_step; u += uv_step; v += uv_step; } } return; } //Writes data into the specified posn of the buffer. //0 == top left, 1 == top right //2 == bot left, 3 == bot right void VideoBuffer::Write(BYTE * data, PINDEX amount, PINDEX posn) { // It appears that a full frame is always written. // We can determine the size of the frame by how much // is written. if (amount == 0) return; PWaitAndSignal mutex(videoBufferMutex); BYTE *yFirst, *ySecond, *u, *v, *srcYFirst, *srcYSecond, *srcU, *srcV; int srcFrameSize = (amount<<1)/3; int srcXSize = (srcFrameSize == (176 * 144) ? 176 : 352 ); int srcYSize = (srcFrameSize == (176 * 144) ? 144 : 288 ); yFirst = buffer; u= buffer + bufferFrameSize; v= buffer + bufferFrameSize + (bufferFrameSize >> 2); srcYFirst = data; srcYSecond = srcYFirst + (xSize == srcXSize ? srcXSize << 1 : srcXSize); srcU = data + srcFrameSize; srcV = data + srcFrameSize + (srcFrameSize >> 2); switch (posn) { case 0: break; case 1: yFirst +=(xSize >> 1); u +=(xSize >> 2); v +=(xSize >> 2); break; case 2: yFirst += (bufferFrameSize >> 1); u += (bufferFrameSize >> 3); v += (bufferFrameSize >> 3); break; case 3: yFirst += (bufferFrameSize >> 1) + (xSize >> 1); u += (bufferFrameSize >> 3) + (xSize >> 2); v += (bufferFrameSize >> 3) + (xSize >> 2); break; default: return; } ySecond = yFirst + xSize; // added down here so that any changes to // yFirst are taken into account - pez // Special case, can fit 'in' images perfectly inside 'out' images if ( xSize == 352 && srcXSize == 176 ) { for(int i=0; i < 144; i+=2) { memcpy(yFirst, srcYFirst, 176); memcpy(ySecond, srcYSecond, 176); memcpy(u, srcU, 88 ); memcpy(v, srcV, 88 ); srcYFirst += 352; srcYSecond += 352; yFirst += 704; ySecond += 704; srcU += 88; srcV += 88; u += 176; v += 176; } } else if ( xSize == 176 && srcXSize == 352 ) { // Copy 1 pixel out of 4 int src_step = 7 * srcXSize; int step = xSize + (xSize >> 1); int srcuv_step = (srcXSize >> 1); int uv_step = (xSize >> 2); for(int i=0; i> 1); int srcuv_step = (srcXSize >> 1); int uv_step = (xSize >> 2); for(int i=0; i> 1); u += (xSize >> 2); v += (xSize >> 2); break; case 2: yFirst += (bufferFrameSize >> 1); u += (bufferFrameSize >> 3); v += (bufferFrameSize >> 3); break; case 3: yFirst += (bufferFrameSize >>1) + (xSize >> 1); u += (bufferFrameSize >> 3) + (xSize >> 2); v += (bufferFrameSize >> 3) + (xSize >> 2); break; default: return; } ySecond = yFirst + xSize; for(int y=0; y < (ySize>>1); y+=2) { memset(yFirst, 0x80, xSize >> 1); // Mid Grey memset(ySecond, 0x80, xSize >> 1); // Mid Grey memset(u, 0x80, xSize >> 2); memset(v, 0x80, xSize >> 2); yFirst += xSize * 2; ySecond += xSize * 2; u += (xSize >> 1); v += (xSize >> 1); } return; } void VideoBuffer::SetSize(int x, int y) { PWaitAndSignal mutex(videoBufferMutex); if ( buffer != NULL ) delete[] buffer; xSize = x; ySize = y; bufferFrameSize = xSize * ySize; videoBufferSize = bufferFrameSize + (bufferFrameSize >> 2 ) + (bufferFrameSize >> 2); // Y + U + V; buffer = new BYTE[ videoBufferSize ]; memset( buffer, 0x80, videoBufferSize); // Set Y, U and V to 0x80 - Mid Grey. } void VideoBuffer::Read(BYTE * data, PINDEX amount) { if (amount == 0) return; PWaitAndSignal mutex(videoBufferMutex); memcpy(data,buffer,amount); } //////////////////////////////////////////////////////////////////////////////////// BOOL VideoDelay::Delay(int frameTime) { if (firstTime) { firstTime = FALSE; previousTime = PTime(); return TRUE; } error += frameTime; PTime now; PTimeInterval delay = now - previousTime; error -= (int)delay.GetMilliSeconds(); previousTime = now; if (error > 0) { #ifdef P_LINUX usleep(error * 1000); #else PThread::Current()->Sleep(error); #endif } else if (error <= -frameTime) { PThread::Current()->Sleep(frameTime); previousTime = PTime(); error = 0; } return error <= -frameTime; } BOOL Conference::DetectNoise(const void * buffer, PINDEX amount) { short *start = (short *)buffer; short *end = start + (amount/2); int sum; sum=0; while (start != end) if(*start<0) sum -= *start++; else sum += *start++; return (sum/amount) > 50; } BOOL Conference::WriteVideo(const PString & thisToken, const void * buffer, PINDEX amount, const PString & roomID) { PWaitAndSignal mutex(roomListMutex); // Check that the room still exists if (videoBufferDict.Contains(roomID) == FALSE) { cout << "ROOM HAS BEEN REMOVED (WriteVideo)" << endl; return FALSE; } VideoBuffer & videoBuffer = videoBufferDict[roomID]; if (singleStream) { videoBuffer.WriteAll((BYTE *)buffer, amount); } else { // The last four elements of spokenList indicate the last // four connections from which audio was received. PINDEX keyIndex = FindTokensVideoPosn(thisToken,roomID); if (keyIndex != P_MAX_INDEX) videoBuffer.Write((BYTE *)buffer, amount, keyIndex); } return TRUE; } BOOL MyH323EndPoint::ReadVideo(const PString & /*thisToken*/, void * buffer, PINDEX amount, const PString & roomID) { PWaitAndSignal mutex(roomListMutex); // Check that the room still exists if (videoBufferDict.Contains(roomID) == FALSE) { cout << "ROOM HAS BEEN REMOVED (ReadVideo)" << endl; return FALSE; } VideoBuffer & videoBuffer = videoBufferDict[roomID]; videoBuffer.Read((BYTE *)buffer,amount); return TRUE; } IncomingVideo::IncomingVideo(MyH323EndPoint & _ep, OpenMCUH323Connection & _conn) : ep(_ep), conn(_conn), width(0), height(0), frameSize(0) { closed = FALSE; } IncomingVideo::~IncomingVideo() { IncomingVideo::Close(); PVideoChannel::Close(); } BOOL IncomingVideo::Write(const void * buffer, PINDEX amount) { amount = (frameSize*3) >> 1; // frameSize==width*height PWaitAndSignal mutex( videoChanMutex ); if (closed){ return FALSE; } conn.OnIncomingVideo(buffer, amount); return TRUE; } void IncomingVideo::SetRenderFrameSize(int _width, int _height) { PTRACE(3,"IncomingVideo Set size"); width = _width; height = _height; frameSize = width * height; } BOOL IncomingVideo::Close() { PWaitAndSignal mutex(videoChanMutex); closed = TRUE; return TRUE; } /////////////////////////////////////////////////////////////////////////// OutgoingVideo::OutgoingVideo(H323EndPoint & _ep, OpenMCUH323Connection & _conn, int framesPerSec, BOOL _videoLarge) : ep(_ep), conn(_conn), videoLarge(_videoLarge) { closed = FALSE; if ( ( framesPerSec>0 ) && ( framesPerSec < 31 ) ) { msBetweenFrames= 1000/framesPerSec; } else { cerr << "Invalid video transmit frame rate. Frame rate should be between 1 and 30 frames per second"<> 1); if (!delay.Delay(msBetweenFrames)) conn.OnOutgoingVideo(buffer, amount); return TRUE; } BOOL OutgoingVideo::Close() { // PWaitAndSignal mutex(videoChanMutex); closed = TRUE; return TRUE; } #endif //NO_MCU_VIDEO