Skip to content

Commit 5e2ca77

Browse files
v-pivamshiVinothini Dharmaraj
andauthored
Added interrupt audio and announce api. (Azure#38916)
* Added interrupt audio and announce api * Added event validation in live test * Added unit test * updating the test * fixing pylint errors --------- Co-authored-by: Vinothini Dharmaraj <[email protected]>
1 parent 1820bd0 commit 5e2ca77

File tree

6 files changed

+209
-5
lines changed

6 files changed

+209
-5
lines changed

sdk/communication/azure-communication-callautomation/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/communication/azure-communication-callautomation",
5-
"Tag": "python/communication/azure-communication-callautomation_bd0d24ba7b"
5+
"Tag": "python/communication/azure-communication-callautomation_40e440aaba"
66
}

sdk/communication/azure-communication-callautomation/azure/communication/callautomation/_call_connection_client.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
HoldRequest,
5050
UnholdRequest,
5151
StartMediaStreamingRequest,
52-
StopMediaStreamingRequest
52+
StopMediaStreamingRequest,
53+
InterruptAudioAndAnnounceRequest,
5354
)
5455
from ._generated.models._enums import RecognizeInputType
5556
from ._shared.auth_policy_utils import get_authentication_policy
@@ -1138,3 +1139,40 @@ def stop_media_streaming(
11381139
stop_media_streaming_request,
11391140
**kwargs
11401141
)
1142+
1143+
@distributed_trace
1144+
def interrupt_audio_and_announce(
1145+
self,
1146+
target_participant: "CommunicationIdentifier",
1147+
play_sources: List[Union['FileSource', 'TextSource', 'SsmlSource']],
1148+
*,
1149+
operation_context: Optional[str] = None,
1150+
**kwargs,
1151+
) -> None:
1152+
"""Interrupt audio and announce to specific participant(s) in this call.
1153+
1154+
:param target_participant: The participant being added.
1155+
:type target_participant: ~azure.communication.callautomation.CommunicationIdentifier
1156+
:param play_sources: A PlaySource representing the source to play.
1157+
:type play_sources: list[~azure.communication.callautomation.FileSource] or
1158+
list[~azure.communication.callautomation.TextSource] or
1159+
list[~azure.communication.callautomation.SsmlSource]
1160+
:keyword operation_context: Value that can be used to track this call and its associated events.
1161+
:paramtype operation_context: str or None
1162+
:return: None
1163+
:rtype: None
1164+
:raises ~azure.core.exceptions.HttpResponseError:
1165+
"""
1166+
1167+
interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest(
1168+
play_sources=[source._to_generated() for source in play_sources] if play_sources else None, # pylint: disable=protected-access
1169+
play_to=serialize_identifier(target_participant),
1170+
operation_context=operation_context,
1171+
kwargs=kwargs,
1172+
)
1173+
1174+
self._call_media_client.interrupt_audio_and_announce(
1175+
self._call_connection_id,
1176+
interrupt_audio_announce_request,
1177+
**kwargs
1178+
)

sdk/communication/azure-communication-callautomation/azure/communication/callautomation/aio/_call_connection_client_async.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
HoldRequest,
5151
UnholdRequest,
5252
StartMediaStreamingRequest,
53-
StopMediaStreamingRequest
53+
StopMediaStreamingRequest,
54+
InterruptAudioAndAnnounceRequest
5455
)
5556
from .._generated.models._enums import RecognizeInputType
5657
from .._shared.auth_policy_utils import get_authentication_policy
@@ -1151,6 +1152,42 @@ async def stop_media_streaming(
11511152
**kwargs
11521153
)
11531154

1155+
@distributed_trace_async
1156+
async def interrupt_audio_and_announce(
1157+
self,
1158+
target_participant: "CommunicationIdentifier",
1159+
play_sources: List[Union['FileSource', 'TextSource', 'SsmlSource']],
1160+
*,
1161+
operation_context: Optional[str] = None,
1162+
**kwargs,
1163+
) -> None:
1164+
"""Play media to specific participant(s) in this call.
1165+
1166+
:param target_participant: The participant being added.
1167+
:type target_participant: ~azure.communication.callautomation.CommunicationIdentifier
1168+
:param play_sources: A PlaySource representing the source to play.
1169+
:type play_sources: list[~azure.communication.callautomation.FileSource] or
1170+
list[~azure.communication.callautomation.TextSource] or
1171+
list[~azure.communication.callautomation.SsmlSource]
1172+
:keyword operation_context: Value that can be used to track this call and its associated events.
1173+
:paramtype operation_context: str or None
1174+
:return: None
1175+
:rtype: None
1176+
:raises ~azure.core.exceptions.HttpResponseError:
1177+
"""
1178+
interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest(
1179+
play_sources=[source._to_generated() for source in play_sources] if play_sources else None, # pylint:disable=protected-access
1180+
play_to=serialize_identifier(target_participant),
1181+
operation_context=operation_context,
1182+
kwargs=kwargs,
1183+
)
1184+
1185+
self._call_media_client.interrupt_audio_and_announce(
1186+
self._call_connection_id,
1187+
interrupt_audio_announce_request,
1188+
**kwargs
1189+
)
1190+
11541191

11551192
async def __aenter__(self) -> "CallConnectionClient":
11561193
await self._client.__aenter__()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"IncomingCall": {"to": {"kind": "communicationUser", "rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511"}}, "from": {"kind": "communicationUser", "rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510"}}, "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "callerDisplayName": "REDACTED", "incomingCallContext": "REDACTED", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921"}, "CallConnected": {"id": "192b4ccc-de4a-41b8-8883-71a9f7461b71", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.CallConnected", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": ""}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.CallConnected"}, "time": "2024-12-23T22:29:23.8584612+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "ParticipantsUpdated": {"id": "0c11fe17-bf61-45bf-8d81-8f5eff03c72a", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.ParticipantsUpdated", "data": {"participants": [{"identifier": {"rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510", "kind": "communicationUser", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510"}}, "isMuted": false, "isOnHold": false}, {"identifier": {"rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511", "kind": "communicationUser", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511"}}, "isMuted": false, "isOnHold": false}], "sequenceNumber": 5, "resultInformation": {"code": 200, "subCode": 0, "message": ""}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.ParticipantsUpdated"}, "time": "2024-12-23T22:29:37.1441684+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioStarted": {"id": "22a42540-9faf-4e13-a271-869e12cd42d8", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioStarted", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioStarted"}, "time": "2024-12-23T22:29:28.8986091+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioPaused": {"id": "bbc2ebc9-549b-4b10-b50b-df112e5efda7", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioPaused", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioPaused"}, "time": "2024-12-23T22:29:30.8983666+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "PlayStarted": {"id": "8c7726d8-5ea5-4ff1-a2f7-194b5583d2bf", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.PlayStarted", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.PlayStarted"}, "time": "2024-12-23T22:29:30.9169166+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "PlayCompleted": {"id": "ec7faa38-8313-4869-a774-14421197f02f", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.PlayCompleted", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.PlayCompleted"}, "time": "2024-12-23T22:29:35.1788036+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioResumed": {"id": "ae45dbbb-f42e-401b-8c96-9e2853ee672c", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioResumed", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioResumed"}, "time": "2024-12-23T22:29:35.1865892+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioCompleted": {"id": "70b82aa5-a093-4d40-9e2b-147c45dff10e", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioCompleted", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 400, "subCode": 8508, "message": "Action falied, the operation was cancelled."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioCompleted"}, "time": "2024-12-23T22:29:37.0473909+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "CallDisconnected": {"id": "ba730173-a88b-4b70-94ba-c31fd6bf5d8d", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.CallDisconnected", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 7000, "message": "The conversation has ended. DiagCode: 0#7000.@"}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.CallDisconnected"}, "time": "2024-12-23T22:29:39.5639151+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}}

sdk/communication/azure-communication-callautomation/tests/test_call_media_client.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
HoldRequest,
3131
UnholdRequest,
3232
StartMediaStreamingRequest,
33-
StopMediaStreamingRequest
33+
StopMediaStreamingRequest,
34+
InterruptAudioAndAnnounceRequest
3435
)
3536
from azure.communication.callautomation._generated.models._enums import RecognizeInputType, DtmfTone
3637
from unittest.mock import Mock
@@ -718,4 +719,55 @@ def test_stop_media_streaming_with_no_param(self):
718719

719720
mock_stop_media_streaming.assert_called_once()
720721
actual_call_connection_id = mock_stop_media_streaming.call_args[0][0]
721-
self.assertEqual(self.call_connection_id,actual_call_connection_id)
722+
self.assertEqual(self.call_connection_id,actual_call_connection_id)
723+
724+
def test_interrupt_audio_and_announce(self):
725+
mock_hold = Mock()
726+
mock_interrupt_audio_and_announce = Mock()
727+
mock_unhold = Mock()
728+
self.call_media_operations.hold = mock_hold
729+
self.call_media_operations.interrupt_audio_and_announce = mock_interrupt_audio_and_announce
730+
self.call_media_operations.unhold = mock_unhold
731+
self.call_media_operations.hold = mock_hold
732+
play_source = FileSource(url=self.url)
733+
operation_context = "context"
734+
735+
self.call_connection_client.hold(
736+
target_participant=self.target_user, play_source=play_source, operation_context=operation_context
737+
)
738+
739+
expected_hold_request = HoldRequest(
740+
target_participant=[serialize_identifier(self.target_user)],
741+
play_source_info=play_source._to_generated(),
742+
operation_context=operation_context,
743+
)
744+
mock_hold.assert_called_once()
745+
actual_hold_request = mock_hold.call_args[0][1]
746+
747+
self.assertEqual(expected_hold_request.play_source_info.file.uri, actual_hold_request.play_source_info.file.uri)
748+
self.assertEqual(expected_hold_request.play_source_info.kind, actual_hold_request.play_source_info.kind)
749+
self.assertEqual(expected_hold_request.operation_context, actual_hold_request.operation_context)
750+
751+
play_sources = [FileSource(url=self.url), TextSource(text='test test test')]
752+
self.call_connection_client.interrupt_audio_and_announce(target_participant=self.target_user, play_sources=play_sources)
753+
754+
expected_interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest(
755+
play_sources=[play_source._to_generated()],
756+
play_to=serialize_identifier(self.target_user),
757+
operation_context=operation_context,
758+
)
759+
mock_interrupt_audio_and_announce.assert_called_once()
760+
actual_interrupt_audio_and_announce_request = mock_interrupt_audio_and_announce.call_args[0][1]
761+
762+
self.assertEqual(expected_interrupt_audio_announce_request.play_sources[0].kind, actual_interrupt_audio_and_announce_request.play_sources[0].kind)
763+
self.assertEqual(expected_interrupt_audio_announce_request.play_to, actual_interrupt_audio_and_announce_request.play_to)
764+
765+
self.call_connection_client.unhold(target_participant=self.target_user, operation_context=operation_context)
766+
767+
expected_hold_request = UnholdRequest(
768+
target_participant=serialize_identifier(self.target_user), operation_context=operation_context
769+
)
770+
mock_unhold.assert_called_once()
771+
actual_hold_request = mock_unhold.call_args[0][1]
772+
773+
self.assertEqual(expected_hold_request.operation_context, actual_hold_request.operation_context)

0 commit comments

Comments
 (0)