/* * 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