Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import com.azure.android.communication.ui.calling.models.CallCompositeAudioSelectionChangedEvent;
import com.azure.android.communication.ui.calling.models.CallCompositeCallStateCode;
import com.azure.android.communication.ui.calling.models.CallCompositeCallStateChangedEvent;
/* <CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.CallCompositeCaptionsReceivedEvent;
/* </CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.CallCompositeDebugInfo;
import com.azure.android.communication.ui.calling.models.CallCompositeDismissedEvent;
import com.azure.android.communication.ui.calling.models.CallCompositeErrorEvent;
Expand Down Expand Up @@ -673,6 +676,40 @@ public void removeOnPictureInPictureChangedEventHandler(
configuration.getCallCompositeEventsHandler().removeOnMultitaskingStateChangedEventHandler(eventHandler);
}

/* <CAPTIONS_RECEIVED> */
/**
* Add on captions received event handler {@link CallCompositeEventHandler}.
*
* <pre>
*
* // add on captions received event handler
* callComposite.addOnCaptionsReceivedEventHandler(event -> {
* // Process captions received event
* System.out.println(event.getSpeakerName());
* System.out.println(event.getCaptionText());
* System.out.println(event.getIsFinal());

Copilot AI Aug 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation references a method getIsFinal() that doesn't exist in the CallCompositeCaptionsReceivedEvent class. This should be removed or the method should be added to the event class.

Suggested change
* System.out.println(event.getIsFinal());

Copilot uses AI. Check for mistakes.
* });
*
* </pre>
*
* @param handler The {@link CallCompositeEventHandler}.
*/
public void addOnCaptionsReceivedEventHandler(
final CallCompositeEventHandler<CallCompositeCaptionsReceivedEvent> handler) {
configuration.getCallCompositeEventsHandler().addOnCaptionsReceivedEventHandler(handler);
}

/**
* Remove on captions received event handler {@link CallCompositeEventHandler}.
*
* @param handler The {@link CallCompositeEventHandler}.
*/
public void removeOnCaptionsReceivedEventHandler(
final CallCompositeEventHandler<CallCompositeCaptionsReceivedEvent> handler) {
configuration.getCallCompositeEventsHandler().removeOnCaptionsReceivedEventHandler(handler);
}
/* </CAPTIONS_RECEIVED> */

/**
* Set {@link CallCompositeParticipantViewData}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@

package com.azure.android.communication.ui.calling.configuration.events


import com.azure.android.communication.ui.calling.CallCompositeEventHandler
import com.azure.android.communication.ui.calling.models.CallCompositeAudioSelectionChangedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeCallStateChangedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeErrorEvent
import com.azure.android.communication.ui.calling.models.CallCompositePictureInPictureChangedEvent
/* <CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.CallCompositeCaptionsReceivedEvent
/* </CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.CallCompositeDismissedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeRemoteParticipantJoinedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeUserReportedIssueEvent
import com.azure.android.communication.ui.calling.models.CallCompositeAudioSelectionChangedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeErrorEvent
import com.azure.android.communication.ui.calling.models.CallCompositeIncomingCallCancelledEvent
import com.azure.android.communication.ui.calling.models.CallCompositeIncomingCallEvent
import com.azure.android.communication.ui.calling.models.CallCompositePictureInPictureChangedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeRemoteParticipantJoinedEvent
import com.azure.android.communication.ui.calling.models.CallCompositeRemoteParticipantLeftEvent
import com.azure.android.communication.ui.calling.models.CallCompositeUserReportedIssueEvent
/* <CALL_START_TIME> */
import java.util.Date
/* </CALL_START_TIME> */
Expand Down Expand Up @@ -50,6 +54,10 @@ internal class CallCompositeEventsHandler {
mutableSetOf<CallCompositeEventHandler<Date>>()
/* </CALL_START_TIME> */

/* <CAPTIONS_RECEIVED> */
private val onCaptionsReceivedHandlers = mutableSetOf<CallCompositeEventHandler<CallCompositeCaptionsReceivedEvent>>()
/* </CAPTIONS_RECEIVED> */

fun getOnErrorHandlers() = errorHandlers.asIterable()

fun addOnErrorEventHandler(errorHandler: CallCompositeEventHandler<CallCompositeErrorEvent>) =
Expand Down Expand Up @@ -145,4 +153,16 @@ internal class CallCompositeEventsHandler {
callStartTimeUpdatedEventHandlers.remove(eventHandler)
}
/* </CALL_START_TIME> */

/* <CAPTIONS_RECEIVED> */
fun addOnCaptionsReceivedEventHandler(handler: CallCompositeEventHandler<CallCompositeCaptionsReceivedEvent>) {
onCaptionsReceivedHandlers.add(handler)
}

fun removeOnCaptionsReceivedEventHandler(handler: CallCompositeEventHandler<CallCompositeCaptionsReceivedEvent>) {
onCaptionsReceivedHandlers.remove(handler)
}

internal fun getCaptionsReceivedEventHandlers() = onCaptionsReceivedHandlers.asIterable()
/* </CAPTIONS_RECEIVED> */
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ internal class DependencyInjectionContainerImpl(

override val captionsRttDataManager by lazy {
CaptionsRttDataManager(
/* <CAPTIONS_RECEIVED> */
configuration,
/* </CAPTIONS_RECEIVED> */
callingService,
appStore,
avatarViewManager,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
/* <CAPTIONS_RECEIVED> */
package com.azure.android.communication.ui.calling.models;

/**
* Call composite captions received event.
*/
public class CallCompositeCaptionsReceivedEvent {
private final String speakerName;
private final String speakerRawId;
private final String captionText;
private final String languageCode;

CallCompositeCaptionsReceivedEvent(
final String speakerName,
final String speakerRawId,
final String captionText,
final String languageCode) {
this.speakerName = speakerName;
this.speakerRawId = speakerRawId;
this.captionText = captionText;
this.languageCode = languageCode;
}

/**
* Get speaker name.
* @return Speaker name
*/
public String getSpeakerName() { return speakerName; }

/**
* Get speaker raw id.
* @return Speaker raw id
*/
public String getSpeakerRawId() { return speakerRawId; }

/**
* Get caption text.
* @return Caption text
*/
public String getCaptionText() { return captionText; }

/**
* Get language code.
* @return Language code
*/
public String getLanguageCode() { return languageCode; }
}
/* </CAPTIONS_RECEIVED> */
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,19 @@ internal fun CallCompositeButtonViewData.setEnabledChangedEventHandler(handler:
internal fun CallCompositeButtonViewData.setVisibleChangedEventHandler(handler: CallCompositeEventHandler<Boolean>) {
this.visibleChangedEventHandler = handler
}

/* <CAPTIONS_RECEIVED> */
internal fun createCallCompositeCaptionsReceivedEvent(
speakerName: String,
speakerRawId: String,
captionText: String,
languageCode: String,
): CallCompositeCaptionsReceivedEvent {
return CallCompositeCaptionsReceivedEvent(
speakerName,
speakerRawId,
captionText,
languageCode
)
}
/* </CAPTIONS_RECEIVED> */
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ package com.azure.android.communication.ui.calling.presentation.manager

import android.graphics.Bitmap
import com.azure.android.communication.common.CommunicationIdentifier
/* <CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
/* </CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.CallCompositeCaptionsData
import com.azure.android.communication.ui.calling.models.CaptionsResultType
import com.azure.android.communication.ui.calling.models.RttMessage
/* <CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.models.createCallCompositeCaptionsReceivedEvent
/* </CAPTIONS_RECEIVED> */
import com.azure.android.communication.ui.calling.presentation.fragment.calling.CallingFragment
import com.azure.android.communication.ui.calling.presentation.fragment.calling.captions.CaptionsRttRecord
import com.azure.android.communication.ui.calling.presentation.fragment.calling.captions.CaptionsRttType
Expand All @@ -32,6 +38,9 @@ import java.util.Date
import kotlin.math.min

internal class CaptionsRttDataManager(
/* <CAPTIONS_RECEIVED> */
private val configuration: CallCompositeConfiguration,
/* </CAPTIONS_RECEIVED> */
private val callingService: CallingService,
private val appStore: AppStore<ReduxState>,
private val avatarViewManager: AvatarViewManager,
Expand Down Expand Up @@ -226,14 +235,39 @@ internal class CaptionsRttDataManager(

if (lastCaptionFromSameUser != null && shouldFinalizeLastCaption(lastCaptionFromSameUser, newCaptionsRecord)) {
lastCaptionFromSameUser = finalizeLastCaption(lastCaptionFromSameUser)
/* <CAPTIONS_RECEIVED> */
notifyCaptionReceived(lastCaptionFromSameUser)
/* </CAPTIONS_RECEIVED> */
}

if (lastCaptionFromSameUser?.isFinal == false) {
updateCaptionsRttRecord(lastCaptionFromSameUser, newCaptionsRecord)
} else {
addNewCaption(newCaptionsRecord)
}

/* <CAPTIONS_RECEIVED> */
if (newCaptionsRecord.isFinal) {
notifyCaptionReceived(newCaptionsRecord)
}
/* </CAPTIONS_RECEIVED> */
}

/* <CAPTIONS_RECEIVED> */
private fun notifyCaptionReceived(finalizedCaptionsRecord: CaptionsRttRecord) {
val event = createCallCompositeCaptionsReceivedEvent(
finalizedCaptionsRecord.displayName ?: "",
finalizedCaptionsRecord.speakerRawId ?: "",
finalizedCaptionsRecord.displayText,
finalizedCaptionsRecord.languageCode ?: ""
)

configuration.callCompositeEventsHandler.getCaptionsReceivedEventHandlers()
.forEach { handler ->
handler.handle(event)
}
}
/* </CAPTIONS_RECEIVED> */

private fun getLastCaptionFromUser(speakerRawId: String?, type: CaptionsRttType): CaptionsRttRecord? {
return captionsAndRttMutableList.lastOrNull { it.type == type && it.speakerRawId == speakerRawId }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,15 @@ class CallCompositeManager(private val context: Context) {
RemoteParticipantJoinedHandler(callComposite, context)
)
}

/* <CAPTIONS_RECEIVED> */
callComposite.addOnCaptionsReceivedEventHandler {
toast(
context,
"Captions received: speakerName: ${it.speakerName}, speakerRawId: ${it.speakerRawId}, captionText: ${it.captionText}, languageCode: ${it.languageCode}"
)
}
/* </CAPTIONS_RECEIVED> */
}

fun dismissCallComposite() {
Expand Down