mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Add screen share receive support and improve video calling rotation.
This commit is contained in:
committed by
Greyson Parrelli
parent
513e5b45c5
commit
b9b2924939
@@ -1,216 +0,0 @@
|
||||
package org.thoughtcrime.securesms.events;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.ringrtc.CameraState;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class CallParticipant {
|
||||
|
||||
public static final CallParticipant EMPTY = createRemote(new CallParticipantId(Recipient.UNKNOWN), Recipient.UNKNOWN, null, new BroadcastVideoSink(null), false, false, 0, true, 0, DeviceOrdinal.PRIMARY);
|
||||
|
||||
private final @NonNull CallParticipantId callParticipantId;
|
||||
private final @NonNull CameraState cameraState;
|
||||
private final @NonNull Recipient recipient;
|
||||
private final @Nullable IdentityKey identityKey;
|
||||
private final @NonNull BroadcastVideoSink videoSink;
|
||||
private final boolean videoEnabled;
|
||||
private final boolean microphoneEnabled;
|
||||
private final long lastSpoke;
|
||||
private final boolean mediaKeysReceived;
|
||||
private final long addedToCallTime;
|
||||
private final @NonNull DeviceOrdinal deviceOrdinal;
|
||||
|
||||
public static @NonNull CallParticipant createLocal(@NonNull CameraState cameraState,
|
||||
@NonNull BroadcastVideoSink renderer,
|
||||
boolean microphoneEnabled)
|
||||
{
|
||||
return new CallParticipant(new CallParticipantId(Recipient.self()),
|
||||
Recipient.self(),
|
||||
null,
|
||||
renderer,
|
||||
cameraState,
|
||||
cameraState.isEnabled() && cameraState.getCameraCount() > 0,
|
||||
microphoneEnabled,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
DeviceOrdinal.PRIMARY);
|
||||
}
|
||||
|
||||
public static @NonNull CallParticipant createRemote(@NonNull CallParticipantId callParticipantId,
|
||||
@NonNull Recipient recipient,
|
||||
@Nullable IdentityKey identityKey,
|
||||
@NonNull BroadcastVideoSink renderer,
|
||||
boolean audioEnabled,
|
||||
boolean videoEnabled,
|
||||
long lastSpoke,
|
||||
boolean mediaKeysReceived,
|
||||
long addedToCallTime,
|
||||
@NonNull DeviceOrdinal deviceOrdinal)
|
||||
{
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, renderer, CameraState.UNKNOWN, videoEnabled, audioEnabled, lastSpoke, mediaKeysReceived, addedToCallTime, deviceOrdinal);
|
||||
}
|
||||
|
||||
private CallParticipant(@NonNull CallParticipantId callParticipantId,
|
||||
@NonNull Recipient recipient,
|
||||
@Nullable IdentityKey identityKey,
|
||||
@NonNull BroadcastVideoSink videoSink,
|
||||
@NonNull CameraState cameraState,
|
||||
boolean videoEnabled,
|
||||
boolean microphoneEnabled,
|
||||
long lastSpoke,
|
||||
boolean mediaKeysReceived,
|
||||
long addedToCallTime,
|
||||
@NonNull DeviceOrdinal deviceOrdinal)
|
||||
{
|
||||
this.callParticipantId = callParticipantId;
|
||||
this.recipient = recipient;
|
||||
this.identityKey = identityKey;
|
||||
this.videoSink = videoSink;
|
||||
this.cameraState = cameraState;
|
||||
this.videoEnabled = videoEnabled;
|
||||
this.microphoneEnabled = microphoneEnabled;
|
||||
this.lastSpoke = lastSpoke;
|
||||
this.mediaKeysReceived = mediaKeysReceived;
|
||||
this.addedToCallTime = addedToCallTime;
|
||||
this.deviceOrdinal = deviceOrdinal;
|
||||
}
|
||||
|
||||
public @NonNull CallParticipant withIdentityKey(@Nullable IdentityKey identityKey) {
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime, deviceOrdinal);
|
||||
}
|
||||
|
||||
public @NonNull CallParticipant withVideoEnabled(boolean videoEnabled) {
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime, deviceOrdinal);
|
||||
}
|
||||
|
||||
public @NonNull CallParticipantId getCallParticipantId() {
|
||||
return callParticipantId;
|
||||
}
|
||||
|
||||
public @NonNull Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public @NonNull String getRecipientDisplayName(@NonNull Context context) {
|
||||
if (recipient.isSelf() && isPrimary()) {
|
||||
return context.getString(R.string.CallParticipant__you);
|
||||
} else if (recipient.isSelf()) {
|
||||
return context.getString(R.string.CallParticipant__you_on_another_device);
|
||||
} else if (isPrimary()) {
|
||||
return recipient.getDisplayName(context);
|
||||
} else {
|
||||
return context.getString(R.string.CallParticipant__s_on_another_device, recipient.getDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull String getShortRecipientDisplayName(@NonNull Context context) {
|
||||
if (recipient.isSelf() && isPrimary()) {
|
||||
return context.getString(R.string.CallParticipant__you);
|
||||
} else if (recipient.isSelf()) {
|
||||
return context.getString(R.string.CallParticipant__you_on_another_device);
|
||||
} else if (isPrimary()) {
|
||||
return recipient.getShortDisplayName(context);
|
||||
} else {
|
||||
return context.getString(R.string.CallParticipant__s_on_another_device, recipient.getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable IdentityKey getIdentityKey() {
|
||||
return identityKey;
|
||||
}
|
||||
|
||||
public @NonNull BroadcastVideoSink getVideoSink() {
|
||||
return videoSink;
|
||||
}
|
||||
|
||||
public @NonNull CameraState getCameraState() {
|
||||
return cameraState;
|
||||
}
|
||||
|
||||
public boolean isVideoEnabled() {
|
||||
return videoEnabled;
|
||||
}
|
||||
|
||||
public boolean isMicrophoneEnabled() {
|
||||
return microphoneEnabled;
|
||||
}
|
||||
|
||||
public @NonNull CameraState.Direction getCameraDirection() {
|
||||
if (cameraState.getActiveDirection() == CameraState.Direction.BACK) {
|
||||
return cameraState.getActiveDirection();
|
||||
}
|
||||
return CameraState.Direction.FRONT;
|
||||
}
|
||||
|
||||
public boolean isMoreThanOneCameraAvailable() {
|
||||
return cameraState.getCameraCount() > 1;
|
||||
}
|
||||
|
||||
public long getLastSpoke() {
|
||||
return lastSpoke;
|
||||
}
|
||||
|
||||
public boolean isMediaKeysReceived() {
|
||||
return mediaKeysReceived;
|
||||
}
|
||||
|
||||
public long getAddedToCallTime() {
|
||||
return addedToCallTime;
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return deviceOrdinal == DeviceOrdinal.PRIMARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CallParticipant that = (CallParticipant) o;
|
||||
return callParticipantId.equals(that.callParticipantId) &&
|
||||
videoEnabled == that.videoEnabled &&
|
||||
microphoneEnabled == that.microphoneEnabled &&
|
||||
lastSpoke == that.lastSpoke &&
|
||||
mediaKeysReceived == that.mediaKeysReceived &&
|
||||
addedToCallTime == that.addedToCallTime &&
|
||||
cameraState.equals(that.cameraState) &&
|
||||
recipient.equals(that.recipient) &&
|
||||
Objects.equals(identityKey, that.identityKey) &&
|
||||
Objects.equals(videoSink, that.videoSink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(callParticipantId, cameraState, recipient, identityKey, videoSink, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String toString() {
|
||||
return "CallParticipant{" +
|
||||
"cameraState=" + cameraState +
|
||||
", recipient=" + recipient.getId() +
|
||||
", identityKey=" + (identityKey == null ? "absent" : "present") +
|
||||
", videoSink=" + (videoSink.getEglBase() == null ? "not initialized" : "initialized") +
|
||||
", videoEnabled=" + videoEnabled +
|
||||
", microphoneEnabled=" + microphoneEnabled +
|
||||
", lastSpoke=" + lastSpoke +
|
||||
", mediaKeysReceived=" + mediaKeysReceived +
|
||||
", addedToCallTime=" + addedToCallTime +
|
||||
'}';
|
||||
}
|
||||
|
||||
public enum DeviceOrdinal {
|
||||
PRIMARY,
|
||||
SECONDARY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.thoughtcrime.securesms.events
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.ringrtc.CameraState
|
||||
import org.whispersystems.libsignal.IdentityKey
|
||||
|
||||
data class CallParticipant constructor(
|
||||
val callParticipantId: CallParticipantId = CallParticipantId(Recipient.UNKNOWN),
|
||||
val recipient: Recipient = Recipient.UNKNOWN,
|
||||
val identityKey: IdentityKey? = null,
|
||||
val videoSink: BroadcastVideoSink = BroadcastVideoSink(),
|
||||
val cameraState: CameraState = CameraState.UNKNOWN,
|
||||
val isVideoEnabled: Boolean = false,
|
||||
val isMicrophoneEnabled: Boolean = false,
|
||||
val lastSpoke: Long = 0,
|
||||
val isMediaKeysReceived: Boolean = true,
|
||||
val addedToCallTime: Long = 0,
|
||||
val isScreenSharing: Boolean = false,
|
||||
private val deviceOrdinal: DeviceOrdinal = DeviceOrdinal.PRIMARY
|
||||
) {
|
||||
val cameraDirection: CameraState.Direction
|
||||
get() = if (cameraState.activeDirection == CameraState.Direction.BACK) cameraState.activeDirection else CameraState.Direction.FRONT
|
||||
|
||||
val isMoreThanOneCameraAvailable: Boolean
|
||||
get() = cameraState.cameraCount > 1
|
||||
|
||||
val isPrimary: Boolean
|
||||
get() = deviceOrdinal == DeviceOrdinal.PRIMARY
|
||||
|
||||
fun getRecipientDisplayName(context: Context): String {
|
||||
return if (recipient.isSelf && isPrimary) {
|
||||
context.getString(R.string.CallParticipant__you)
|
||||
} else if (recipient.isSelf) {
|
||||
context.getString(R.string.CallParticipant__you_on_another_device)
|
||||
} else if (isPrimary) {
|
||||
recipient.getDisplayName(context)
|
||||
} else {
|
||||
context.getString(R.string.CallParticipant__s_on_another_device, recipient.getDisplayName(context))
|
||||
}
|
||||
}
|
||||
|
||||
fun getShortRecipientDisplayName(context: Context): String {
|
||||
return if (recipient.isSelf && isPrimary) {
|
||||
context.getString(R.string.CallParticipant__you)
|
||||
} else if (recipient.isSelf) {
|
||||
context.getString(R.string.CallParticipant__you_on_another_device)
|
||||
} else if (isPrimary) {
|
||||
recipient.getShortDisplayName(context)
|
||||
} else {
|
||||
context.getString(R.string.CallParticipant__s_on_another_device, recipient.getShortDisplayName(context))
|
||||
}
|
||||
}
|
||||
|
||||
fun withIdentityKey(identityKey: IdentityKey?): CallParticipant {
|
||||
return copy(identityKey = identityKey)
|
||||
}
|
||||
|
||||
fun withVideoEnabled(videoEnabled: Boolean): CallParticipant {
|
||||
return copy(isVideoEnabled = videoEnabled)
|
||||
}
|
||||
|
||||
fun withScreenSharingEnabled(enable: Boolean): CallParticipant {
|
||||
return copy(isScreenSharing = enable)
|
||||
}
|
||||
|
||||
enum class DeviceOrdinal {
|
||||
PRIMARY, SECONDARY
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val EMPTY: CallParticipant = CallParticipant()
|
||||
|
||||
@JvmStatic
|
||||
fun createLocal(
|
||||
cameraState: CameraState,
|
||||
renderer: BroadcastVideoSink,
|
||||
microphoneEnabled: Boolean
|
||||
): CallParticipant {
|
||||
return CallParticipant(
|
||||
callParticipantId = CallParticipantId(Recipient.self()),
|
||||
recipient = Recipient.self(),
|
||||
videoSink = renderer,
|
||||
cameraState = cameraState,
|
||||
isVideoEnabled = cameraState.isEnabled && cameraState.cameraCount > 0,
|
||||
isMicrophoneEnabled = microphoneEnabled
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun createRemote(
|
||||
callParticipantId: CallParticipantId,
|
||||
recipient: Recipient,
|
||||
identityKey: IdentityKey?,
|
||||
renderer: BroadcastVideoSink,
|
||||
audioEnabled: Boolean,
|
||||
videoEnabled: Boolean,
|
||||
lastSpoke: Long,
|
||||
mediaKeysReceived: Boolean,
|
||||
addedToCallTime: Long,
|
||||
isScreenSharing: Boolean,
|
||||
deviceOrdinal: DeviceOrdinal
|
||||
): CallParticipant {
|
||||
return CallParticipant(
|
||||
callParticipantId = callParticipantId,
|
||||
recipient = recipient,
|
||||
identityKey = identityKey,
|
||||
videoSink = renderer,
|
||||
isVideoEnabled = videoEnabled,
|
||||
isMicrophoneEnabled = audioEnabled,
|
||||
lastSpoke = lastSpoke,
|
||||
isMediaKeysReceived = mediaKeysReceived,
|
||||
addedToCallTime = addedToCallTime,
|
||||
isScreenSharing = isScreenSharing,
|
||||
deviceOrdinal = deviceOrdinal
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class WebRtcViewModel {
|
||||
this.participantLimit = state.getCallInfoState().getParticipantLimit();
|
||||
this.localParticipant = CallParticipant.createLocal(state.getLocalDeviceState().getCameraState(),
|
||||
state.getVideoState().getLocalSink() != null ? state.getVideoState().getLocalSink()
|
||||
: new BroadcastVideoSink(null),
|
||||
: new BroadcastVideoSink(),
|
||||
state.getLocalDeviceState().isMicrophoneEnabled());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user