Skip to content

Commit

Permalink
Merge pull request #2600 from nextcloud/split-call-participants-and-p…
Browse files Browse the repository at this point in the history
…eer-connections

Split call participants and peer connections
  • Loading branch information
mahibi authored Jan 16, 2023
2 parents 2e2e96c + 67e259f commit a87f2fb
Show file tree
Hide file tree
Showing 14 changed files with 2,388 additions and 395 deletions.
566 changes: 236 additions & 330 deletions app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,65 +1,104 @@
package com.nextcloud.talk.adapters;

import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.nextcloud.talk.call.CallParticipantModel;
import com.nextcloud.talk.utils.ApiUtils;

import org.webrtc.EglBase;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;

public class ParticipantDisplayItem {
private String baseUrl;

public interface Observer {
void onChange();
}

/**
* Shared handler to receive change notifications from the model on the main thread.
*/
private static final Handler handler = new Handler(Looper.getMainLooper());

private final ParticipantDisplayItemNotifier participantDisplayItemNotifier = new ParticipantDisplayItemNotifier();

private final String baseUrl;
private final String defaultGuestNick;
private final EglBase rootEglBase;

private final String session;
private final String streamType;

private final CallParticipantModel callParticipantModel;

private final CallParticipantModel.Observer callParticipantModelObserver = this::updateFromModel;

private String userId;
private String session;
private boolean connected;
private PeerConnection.IceConnectionState iceConnectionState;
private String nick;
private final String defaultGuestNick;
private String urlForAvatar;
private MediaStream mediaStream;
private String streamType;
private boolean streamEnabled;
private EglBase rootEglBase;
private boolean isAudioEnabled;

public ParticipantDisplayItem(String baseUrl, String userId, String session, boolean connected, String nick, String defaultGuestNick, MediaStream mediaStream, String streamType, boolean streamEnabled, EglBase rootEglBase) {
public ParticipantDisplayItem(String baseUrl, String defaultGuestNick, EglBase rootEglBase, String streamType,
CallParticipantModel callParticipantModel) {
this.baseUrl = baseUrl;
this.userId = userId;
this.session = session;
this.connected = connected;
this.nick = nick;
this.defaultGuestNick = defaultGuestNick;
this.mediaStream = mediaStream;
this.streamType = streamType;
this.streamEnabled = streamEnabled;
this.rootEglBase = rootEglBase;

this.updateUrlForAvatar();
this.session = callParticipantModel.getSessionId();
this.streamType = streamType;

this.callParticipantModel = callParticipantModel;
this.callParticipantModel.addObserver(callParticipantModelObserver, handler);

updateFromModel();
}

public String getUserId() {
return userId;
public void destroy() {
this.callParticipantModel.removeObserver(callParticipantModelObserver);
}

public void setUserId(String userId) {
this.userId = userId;
private void updateFromModel() {
userId = callParticipantModel.getUserId();
nick = callParticipantModel.getNick();

this.updateUrlForAvatar();
}

public String getSession() {
return session;
}
if ("screen".equals(streamType)) {
iceConnectionState = callParticipantModel.getScreenIceConnectionState();
mediaStream = callParticipantModel.getScreenMediaStream();
isAudioEnabled = true;
streamEnabled = true;
} else {
iceConnectionState = callParticipantModel.getIceConnectionState();
mediaStream = callParticipantModel.getMediaStream();
isAudioEnabled = callParticipantModel.isAudioAvailable() != null ?
callParticipantModel.isAudioAvailable() : false;
streamEnabled = callParticipantModel.isVideoAvailable() != null ?
callParticipantModel.isVideoAvailable() : false;
}

public void setSession(String session) {
this.session = session;
participantDisplayItemNotifier.notifyChange();
}

public boolean isConnected() {
return connected;
private void updateUrlForAvatar() {
if (!TextUtils.isEmpty(userId)) {
urlForAvatar = ApiUtils.getUrlForAvatar(baseUrl, userId, true);
} else {
urlForAvatar = ApiUtils.getUrlForGuestAvatar(baseUrl, getNick(), true);
}
}

public void setConnected(boolean connected) {
this.connected = connected;
public boolean isConnected() {
return iceConnectionState == PeerConnection.IceConnectionState.CONNECTED ||
iceConnectionState == PeerConnection.IceConnectionState.COMPLETED ||
// If there is no connection state that means that no connection is needed, so it is a special case that is
// also seen as "connected".
iceConnectionState == null;
}

public String getNick() {
Expand All @@ -70,62 +109,32 @@ public String getNick() {
return nick;
}

public void setNick(String nick) {
this.nick = nick;

this.updateUrlForAvatar();
}

public String getUrlForAvatar() {
return urlForAvatar;
}

private void updateUrlForAvatar() {
if (!TextUtils.isEmpty(userId)) {
urlForAvatar = ApiUtils.getUrlForAvatar(baseUrl, userId, true);
} else {
urlForAvatar = ApiUtils.getUrlForGuestAvatar(baseUrl, getNick(), true);
}
}

public MediaStream getMediaStream() {
return mediaStream;
}

public void setMediaStream(MediaStream mediaStream) {
this.mediaStream = mediaStream;
}

public String getStreamType() {
return streamType;
}

public void setStreamType(String streamType) {
this.streamType = streamType;
}

public boolean isStreamEnabled() {
return streamEnabled;
}

public void setStreamEnabled(boolean streamEnabled) {
this.streamEnabled = streamEnabled;
}

public EglBase getRootEglBase() {
return rootEglBase;
}

public void setRootEglBase(EglBase rootEglBase) {
this.rootEglBase = rootEglBase;
}

public boolean isAudioEnabled() {
return isAudioEnabled;
}

public void setAudioEnabled(boolean audioEnabled) {
isAudioEnabled = audioEnabled;
public void addObserver(Observer observer) {
participantDisplayItemNotifier.addObserver(observer);
}

public void removeObserver(Observer observer) {
participantDisplayItemNotifier.removeObserver(observer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Nextcloud Talk application
*
* @author Daniel Calviño Sánchez
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.adapters;

import com.nextcloud.talk.signaling.SignalingMessageReceiver;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;

/**
* Helper class to register and notify ParticipantDisplayItem.Observers.
*
* This class is only meant for internal use by ParticipantDisplayItem; observers must register themselves against a
* ParticipantDisplayItem rather than against a ParticipantDisplayItemNotifier.
*/
class ParticipantDisplayItemNotifier {

private final Set<ParticipantDisplayItem.Observer> participantDisplayItemObservers = new LinkedHashSet<>();

public synchronized void addObserver(ParticipantDisplayItem.Observer observer) {
if (observer == null) {
throw new IllegalArgumentException("ParticipantDisplayItem.Observer can not be null");
}

participantDisplayItemObservers.add(observer);
}

public synchronized void removeObserver(ParticipantDisplayItem.Observer observer) {
participantDisplayItemObservers.remove(observer);
}

public synchronized void notifyChange() {
for (ParticipantDisplayItem.Observer observer : new ArrayList<>(participantDisplayItemObservers)) {
observer.onChange();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class ParticipantsAdapter extends BaseAdapter {

private static final String TAG = "ParticipantsAdapter";

private final ParticipantDisplayItem.Observer participantDisplayItemObserver = this::notifyDataSetChanged;

private final Context mContext;
private final ArrayList<ParticipantDisplayItem> participantDisplayItems;
private final RelativeLayout gridViewWrapper;
Expand All @@ -50,8 +52,17 @@ public ParticipantsAdapter(Context mContext,

this.participantDisplayItems = new ArrayList<>();
this.participantDisplayItems.addAll(participantDisplayItems.values());

for (ParticipantDisplayItem participantDisplayItem : this.participantDisplayItems) {
participantDisplayItem.addObserver(participantDisplayItemObserver);
}
}

public void destroy() {
for (ParticipantDisplayItem participantDisplayItem : participantDisplayItems) {
participantDisplayItem.removeObserver(participantDisplayItemObserver);
}
}

@Override
public int getCount() {
Expand Down
Loading

0 comments on commit a87f2fb

Please sign in to comment.