From a2075438435daf06b1192f2b8bba2f2cc71bc190 Mon Sep 17 00:00:00 2001
From: Yalu Zhang <yalu.zhang@iopsys.eu>
Date: Wed, 10 Jul 2024 17:02:19 +0200
Subject: [PATCH] Pass DTMF to Voicemail applications correctly

---
 src/channels/chan_voicemngr.c | 57 +++++++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 13 deletions(-)

diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index 9f20edd..9f96818 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -3138,17 +3138,33 @@ static void handle_dtmf(enum LINE_EVENT event,
 	gettimeofday(&tim, NULL);
 	p = sub->parent;
 
-	if (p->dtmf_first < 0) {
+	if (p->dtmf_first < 0) { // DTMF pressed
 		p->dtmf_first = dtmf_button;
 		ast_debug(9,"Pressed DTMF %s\n", dtmfMap->name);
+		if (owner) {
+			struct ast_channel *bridged_chan = ast_channel_bridge_peer(owner);
+			if (bridged_chan) {
+				const struct ast_channel_tech *chan_tech = ast_channel_tech(bridged_chan);
+				if (chan_tech && chan_tech->type && *chan_tech->type) {
+					ast_debug(1, "debug_tmp: the type of the bridged channel is %s, sub->direct_extension = %d\n",
+							chan_tech->type, sub->direct_extension);
+				} else {
+					ast_debug(1, "debug_tmp: the type of the bridged channel is unknown, sub->direct_extension = %d\n",
+							sub->direct_extension);
+				}
+				ast_channel_unref(bridged_chan);
+			} else {
+				ast_debug(1, "debug_tmp: there is no bridged channel, sub->direct_extension = %d. is there a bridge? %s\n",
+						sub->direct_extension, ast_channel_internal_bridge(owner) ? "yes" : "no");
+			}
+		}
 		if (owner && chan_voicemngr_should_relay_dtmf(sub) && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || sub->direct_extension == 1)) {
 			// INCALL
 			send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_BEGIN);
 		}
 
 		/* Do not send AST_FRAME_DTMF_BEGIN to allow DSP-generated tone to pass through */
-	}
-	else if (p->dtmf_first == dtmf_button) {
+	} else if (p->dtmf_first == dtmf_button) { // DTMF released
 		ast_log(LOG_NOTICE,"Released DTMF %s\n", dtmfMap->name);
 		//ast_log(LOG_DTMF, "Detected DTMF %c, line %d\n", dtmfMap->c, sub->parent->line_id);
 
@@ -3179,8 +3195,29 @@ static void handle_dtmf(enum LINE_EVENT event,
 			if (sub->channel_state == OFFHOOK) {
 				sub->channel_state = DIALING;
 				//ast_debug(5,"Set to state %s.\n", state2str(sub->channel_state));
-			}
-			else if (sub->channel_state != INCALL) {
+			} else if (sub->channel_state == INCALL) {
+				if (owner) {
+					struct ast_channel *bridged_chan = ast_channel_bridge_peer(owner);
+					if (bridged_chan) {
+						const struct ast_channel_tech *chan_tech = ast_channel_tech(bridged_chan);
+						if (chan_tech && chan_tech->type && *chan_tech->type) {
+							ast_debug(1, "debug_tmp: the type of the bridged channel is %s, sub->direct_extension = %d\n",
+									chan_tech->type, sub->direct_extension);
+						} else {
+							ast_debug(1, "debug_tmp: the type of the bridged channel is unknown, sub->direct_extension = %d\n",
+									sub->direct_extension);
+						}
+						ast_channel_unref(bridged_chan);
+					} else {
+						ast_debug(1, "debug_tmp: there is no bridged channel, sub->direct_extension = %d. is there a bridge? %s\n",
+								sub->direct_extension, ast_channel_internal_bridge(owner) ? "yes" : "no");
+					}
+				}
+				if (owner && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || sub->direct_extension)) {
+					// INCALL
+					send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_END);
+				}
+			} else {
 				struct ast_frame f = { 0, };
 				f.subclass.integer = dtmf_button;
 				f.src = "TELCHAN";
@@ -3192,15 +3229,9 @@ static void handle_dtmf(enum LINE_EVENT event,
 					//ast_debug(5,"DTMF %s queuing frame.\n", dtmfMap->name);
 					ast_queue_frame(owner, &f);
 				}
-			} else {
-				if (owner && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || sub->direct_extension)) {
-					// INCALL
-					send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_END);
-				}
 			}
-		}
-	}
-	else {
+		} // end of if (p->hf_detected)
+	} else {
 		p->dtmf_first = -1;
 	}
 }
-- 
GitLab