Index: channels/chan_h323.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_h323.c,v
retrieving revision 1.115
diff -u -r1.115 chan_h323.c
--- channels/chan_h323.c	19 May 2005 16:17:08 -0000	1.115
+++ channels/chan_h323.c	19 May 2005 18:40:39 -0000
@@ -83,6 +83,7 @@
 progress_cb on_progress;
 rfc2833_cb on_set_rfc2833_payload;
 hangup_cb on_hangup;
+setcapabilities_cb on_setcapabilities;
 
 /* global debug flag */
 int h323debug;
@@ -1014,9 +1015,7 @@
 	else
 		memcpy(&pvt->options, &global_options, sizeof(pvt->options));
 
-	/* pass on our capabilites to the H.323 stack */
 	ast_mutex_lock(&caplock);
-	h323_set_capability(pvt->capability, pvt->dtmfmode);
 	/* Generate unique channel identifier */
 	snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
 	tmp1[sizeof(tmp1)-1] = '\0';
@@ -1511,6 +1510,26 @@
 		ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
 }
 
+static void set_local_capabilities(unsigned call_reference, const char *token)
+{
+	struct oh323_pvt *pvt;
+	int capability, dtmfmode;
+
+	if (h323debug)
+		ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
+
+	pvt = find_call_locked(call_reference, token);
+	if (!pvt)
+		return;
+	capability = pvt->capability;
+	dtmfmode = pvt->dtmfmode;
+	ast_mutex_unlock(&pvt->lock);
+	h323_set_capabilities(token, capability, dtmfmode);
+
+	if (h323debug)
+		ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
+}
+
 static void *do_monitor(void *data)
 {
 	int res;
@@ -2160,14 +2179,6 @@
 		alias = alias->next;
 	}
 
-	/* Add our capabilities */
-	ast_mutex_lock(&caplock);
-	if (h323_set_capability(capability, dtmfmode)) {
-		ast_log(LOG_ERROR, "Capabilities failure, this is bad.\n");
-		ast_mutex_unlock(&caplock);
-		return -1;
-	}
-	ast_mutex_unlock(&caplock);
 	return 0;
 }
 
@@ -2383,7 +2394,8 @@
 						answer_call,
 						progress,
 						set_dtmf_payload,
-						hangup_connection);
+						hangup_connection,
+						set_local_capabilities);
 		/* start the h.323 listener */
 		if (h323_start_listener(h323_signalling_port, bindaddr)) {
 			ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
Index: channels/h323/ast_h323.cpp
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/ast_h323.cpp,v
retrieving revision 1.76
diff -u -r1.76 ast_h323.cpp
--- channels/h323/ast_h323.cpp	19 May 2005 16:16:47 -0000	1.76
+++ channels/h323/ast_h323.cpp	19 May 2005 18:40:43 -0000
@@ -282,7 +282,15 @@
 }
 
 /** MyH323EndPoint 
-  * The fullAddress parameter is used directly in the MakeCall method so
+  */
+MyH323EndPoint::MyH323EndPoint()
+		: H323EndPoint()
+{
+	// Capabilities will be negotiated on per-connection basis
+	capabilities.RemoveAll();
+}
+
+/** The fullAddress parameter is used directly in the MakeCall method so
   * the General form for the fullAddress argument is :
   * [alias@][transport$]host[:port]
   * default values:	alias = the same value as host.
@@ -359,11 +367,6 @@
 	terminalType = e_GatewayOnly;
 }
 
-H323Capabilities MyH323EndPoint::GetCapabilities(void)
-{
-	return capabilities;
-}
-
 BOOL MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason)
 {
 	if (h323debug) {
@@ -915,6 +918,12 @@
 	}
 }
 
+void MyH323Connection::OnSetLocalCapabilities()
+{
+	if (on_setcapabilities)
+		on_setcapabilities(GetCallReference(), (const char *)callToken);
+}
+
 BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
 					       const H245_MultiplexCapability * muxCap,
 					       H245_TerminalCapabilitySetReject & reject)
@@ -963,6 +972,73 @@
 	return connectionState != ShuttingDownConnection;
 }
 
+void MyH323Connection::SetCapabilities(int cap, int dtmfMode)
+{
+	int g711Frames = 20;
+//	int gsmFrames  = 4;
+	PINDEX lastcap = -1; /* last common capability index */
+
+#if 0
+	if (cap & AST_FORMAT_SPEEX) {
+		/* Not real sure if Asterisk acutally supports all
+		   of the various different bit rates so add them 
+		   all and figure it out later*/
+
+		localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability());
+		localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability());
+		localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability());
+		localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability());
+		localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability());
+	}
+#endif 
+	if (cap & AST_FORMAT_G729A) {
+		AST_G729ACapability *g729aCap;
+		AST_G729Capability *g729Cap;
+		lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability);
+		lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability);
+	}
+	
+	if (cap & AST_FORMAT_G723_1) {
+		H323_G7231Capability *g7231Cap;
+		lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
+	} 
+#if 0
+	if (cap & AST_FORMAT_GSM) {
+		H323_GSM0610Capability *gsmCap;
+	    	lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
+	    	gsmCap->SetTxFramesInPacket(gsmFrames);
+	} 
+#endif
+	if (cap & AST_FORMAT_ULAW) {
+		H323_G711Capability *g711uCap;
+	    	lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
+		g711uCap->SetTxFramesInPacket(g711Frames);
+	} 
+
+	if (cap & AST_FORMAT_ALAW) {
+		H323_G711Capability *g711aCap;
+		lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
+		g711aCap->SetTxFramesInPacket(g711Frames);
+	}
+
+	lastcap++;
+	lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
+
+	lastcap++;
+	mode = dtmfMode;
+	if (dtmfMode == H323_DTMF_INBAND) {
+		localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
+		sendUserInputMode = SendUserInputAsTone;
+	} else {
+		localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
+		sendUserInputMode = SendUserInputAsInlineRFC2833;
+	}
+
+	if (h323debug) {
+		cout <<  "Allowed Codecs:\n\t" << setprecision(2) << localCapabilities << endl;
+	}
+}
+
 /* MyH323_ExternalRTPChannel */
 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
 						     const H323Capability & capability,
@@ -1106,7 +1182,8 @@
  			    answer_call_cb	acfunc,
 			    progress_cb		pgfunc,
 			    rfc2833_cb		dtmffunc,
-			    hangup_cb		hangupfunc)
+			    hangup_cb		hangupfunc,
+			    setcapabilities_cb	capabilityfunc)
 {
 	on_incoming_call = ifunc;
 	on_outgoing_call = sfunc;
@@ -1120,90 +1197,30 @@
 	on_progress = pgfunc;
 	on_set_rfc2833_payload = dtmffunc;
 	on_hangup = hangupfunc;
+	on_setcapabilities = capabilityfunc;
 }
 
 /**
  * Add capability to the capability table of the end point. 
  */
-int h323_set_capability(int cap, int dtmfMode)
+int h323_set_capabilities(const char *token, int cap, int dtmfMode)
 {
-	H323Capabilities oldcaps;
-	PStringArray codecs;
-	int g711Frames = 20;
-//	int gsmFrames  = 4;
-	PINDEX lastcap = -1; /* last common capability index */
+	MyH323Connection *conn;
 
 	if (!h323_end_point_exist()) {
 		cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
 		return 1;
 	}
 
-	/* clean up old capabilities list before changing */
-	oldcaps = endPoint->GetCapabilities();
-	for (PINDEX i=0; i< oldcaps.GetSize(); i++) {
-                 codecs.AppendString(oldcaps[i].GetFormatName());
-        }
-        endPoint->RemoveCapabilities(codecs);
-
-#if 0
-	if (cap & AST_FORMAT_SPEEX) {
-		/* Not real sure if Asterisk acutally supports all
-		   of the various different bit rates so add them 
-		   all and figure it out later*/
-
-		endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
-	}
-#endif 
-	if (cap & AST_FORMAT_G729A) {
-		AST_G729ACapability *g729aCap;
-		AST_G729Capability *g729Cap;
-		lastcap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
-		lastcap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
-	}
-	
-	if (cap & AST_FORMAT_G723_1) {
-		H323_G7231Capability *g7231Cap;
-		lastcap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
-	} 
-#if 0
-	if (cap & AST_FORMAT_GSM) {
-		H323_GSM0610Capability *gsmCap;
-	    	lastcap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
-	    	gsmCap->SetTxFramesInPacket(gsmFrames);
-	} 
-#endif
-	if (cap & AST_FORMAT_ULAW) {
-		H323_G711Capability *g711uCap;
-	    	lastcap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
-		g711uCap->SetTxFramesInPacket(g711Frames);
-	} 
-
-	if (cap & AST_FORMAT_ALAW) {
-		H323_G711Capability *g711aCap;
-		lastcap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
-		g711aCap->SetTxFramesInPacket(g711Frames);
-	}
-
-	lastcap++;
-	lastcap = endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
-
-	lastcap++;
-	mode = dtmfMode;
-	if (dtmfMode == H323_DTMF_INBAND) {
-		endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
-		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
-	} else {
-		endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
-		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
+	PString myToken(token);
+	conn = (MyH323Connection *)endPoint->FindConnectionWithLock(myToken);
+	if (!conn) {
+		cout << " ERROR: [h323_set_capability] Unable to find connection " << token << endl;
+		return 1;
 	}
+	conn->SetCapabilities(cap, dtmfMode);
+	conn->Unlock();
 
-	if (h323debug) {
-		cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
-	}
 	return 0;
 }
 
Index: channels/h323/ast_h323.h
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/ast_h323.h,v
retrieving revision 1.32
diff -u -r1.32 ast_h323.h
--- channels/h323/ast_h323.h	4 Apr 2005 07:06:26 -0000	1.32
+++ channels/h323/ast_h323.h	19 May 2005 18:40:43 -0000
@@ -128,6 +128,7 @@
 	PCLASSINFO(MyH323EndPoint, H323EndPoint);
 
 	public:
+	MyH323EndPoint();
 	int MakeCall(const PString &, PString &, unsigned int *, call_options_t *opts);
 	BOOL ClearCall(const PString &, H323Connection::CallEndReason reason);
 	BOOL ClearCall(const PString &);
@@ -137,7 +138,6 @@
 	void OnConnectionCleared(H323Connection &, const PString &);
 	H323Connection * CreateConnection(unsigned, void *);
 	void SendUserTone(const PString &, char);
-	H323Capabilities GetCapabilities(void);
 	BOOL OnConnectionForwarded(H323Connection &, const PString &, const H323SignalPDU &);
 	BOOL ForwardConnection(H323Connection &, const PString &, const H323SignalPDU &);
     	void SetEndpointTypeInfo( H225_EndpointType & info ) const;
@@ -173,6 +173,8 @@
 	void OnUserInputString(const PString &value);
 	BOOL OnReceivedProgress(const H323SignalPDU &);
 	void OnSendCapabilitySet(H245_TerminalCapabilitySet &);
+	void OnSetLocalCapabilities();
+	void SetCapabilities(int, int);
 	BOOL OnReceivedCapabilitySet(const H323Capabilities &, const H245_MultiplexCapability *,
 				     H245_TerminalCapabilitySetReject &);
 	void SetCause(int _cause) { cause = _cause; };
Index: channels/h323/chan_h323.h
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/chan_h323.h,v
retrieving revision 1.41
diff -u -r1.41 chan_h323.h
--- channels/h323/chan_h323.h	19 May 2005 16:16:47 -0000	1.41
+++ channels/h323/chan_h323.h	19 May 2005 18:40:44 -0000
@@ -169,6 +169,9 @@
 typedef void (*hangup_cb)(unsigned, const char *, int);
 extern hangup_cb on_hangup;
 
+typedef void (*setcapabilities_cb)(unsigned, const char *);
+extern setcapabilities_cb on_setcapabilities;
+
 /* debug flag */
 extern int h323debug;
 
@@ -202,8 +205,9 @@
  				    answer_call_cb,
 				    progress_cb,
 				    rfc2833_cb,
-				    hangup_cb);
-	int h323_set_capability(int, int);
+				    hangup_cb,
+				    setcapabilities_cb);
+	int h323_set_capabilities(const char *, int, int);
 	int h323_set_alias(struct oh323_alias *);
 	int h323_set_gk(int, char *, char *);
 	void h323_set_id(char *);
