浏览代码

Merge pull request #2545 from nextcloud/add-listener-for-data-channel-messages

Add listener for data channel messages
Tim Krüger 2 年之前
父节点
当前提交
5786baaeb7

+ 136 - 24
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -76,7 +76,6 @@ import com.nextcloud.talk.models.json.generic.GenericOverall;
 import com.nextcloud.talk.models.json.participants.Participant;
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
 import com.nextcloud.talk.models.json.signaling.DataChannelMessage;
-import com.nextcloud.talk.models.json.signaling.DataChannelMessageNick;
 import com.nextcloud.talk.models.json.signaling.NCMessagePayload;
 import com.nextcloud.talk.models.json.signaling.NCSignalingMessage;
 import com.nextcloud.talk.models.json.signaling.Signaling;
@@ -264,9 +263,13 @@ public class CallActivity extends CallBaseActivity {
     private InternalSignalingMessageSender internalSignalingMessageSender = new InternalSignalingMessageSender();
     private SignalingMessageSender signalingMessageSender;
 
+    private Map<String, OfferAnswerNickProvider> offerAnswerNickProviders = new HashMap<>();
+
     private Map<String, SignalingMessageReceiver.CallParticipantMessageListener> callParticipantMessageListeners =
         new HashMap<>();
 
+    private Map<String, PeerConnectionWrapper.DataChannelMessageListener> dataChannelMessageListeners = new HashMap<>();
+
     private SignalingMessageReceiver.ParticipantListMessageListener participantListMessageListener = new SignalingMessageReceiver.ParticipantListMessageListener() {
 
         @Override
@@ -2006,6 +2009,19 @@ public class CallActivity extends CallBaseActivity {
                     new CallActivityCallParticipantMessageListener(sessionId);
                 callParticipantMessageListeners.put(sessionId, callParticipantMessageListener);
                 signalingMessageReceiver.addListener(callParticipantMessageListener, sessionId);
+
+                // DataChannel messages are sent only in video peers; (sender) screen peers do not even open them.
+                PeerConnectionWrapper.DataChannelMessageListener dataChannelMessageListener =
+                    new CallActivityDataChannelMessageListener(sessionId);
+                dataChannelMessageListeners.put(sessionId, dataChannelMessageListener);
+                peerConnectionWrapper.addListener(dataChannelMessageListener);
+            }
+
+            if (!publisher && !hasExternalSignalingServer && offerAnswerNickProviders.get(sessionId) == null) {
+                OfferAnswerNickProvider offerAnswerNickProvider = new OfferAnswerNickProvider();
+                offerAnswerNickProviders.put(sessionId, offerAnswerNickProvider);
+                signalingMessageReceiver.addListener(offerAnswerNickProvider.getVideoWebRtcMessageListener(), sessionId, "video");
+                signalingMessageReceiver.addListener(offerAnswerNickProvider.getScreenWebRtcMessageListener(), sessionId, "screen");
             }
 
             if (publisher) {
@@ -2032,6 +2048,10 @@ public class CallActivity extends CallBaseActivity {
         if (!(peerConnectionWrappers = getPeerConnectionWrapperListForSessionId(sessionId)).isEmpty()) {
             for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrappers) {
                 if (peerConnectionWrapper.getSessionId().equals(sessionId)) {
+                    if (!justScreen && VIDEO_STREAM_TYPE_VIDEO.equals(peerConnectionWrapper.getVideoStreamType())) {
+                        PeerConnectionWrapper.DataChannelMessageListener dataChannelMessageListener = dataChannelMessageListeners.remove(sessionId);
+                        peerConnectionWrapper.removeListener(dataChannelMessageListener);
+                    }
                     String videoStreamType = peerConnectionWrapper.getVideoStreamType();
                     if (VIDEO_STREAM_TYPE_SCREEN.equals(videoStreamType) || !justScreen) {
                         runOnUiThread(() -> removeMediaStream(sessionId, videoStreamType));
@@ -2044,6 +2064,12 @@ public class CallActivity extends CallBaseActivity {
         if (!justScreen) {
             SignalingMessageReceiver.CallParticipantMessageListener listener = callParticipantMessageListeners.remove(sessionId);
             signalingMessageReceiver.removeListener(listener);
+
+            OfferAnswerNickProvider offerAnswerNickProvider = offerAnswerNickProviders.remove(sessionId);
+            if (offerAnswerNickProvider != null) {
+                signalingMessageReceiver.removeListener(offerAnswerNickProvider.getVideoWebRtcMessageListener());
+                signalingMessageReceiver.removeListener(offerAnswerNickProvider.getScreenWebRtcMessageListener());
+            }
         }
     }
 
@@ -2149,24 +2175,6 @@ public class CallActivity extends CallBaseActivity {
                     toggleMedia(enableVideo, true);
                 }
             }
-        } else if (peerConnectionEvent.getPeerConnectionEventType() ==
-            PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE) {
-            if (participantDisplayItems.get(participantDisplayItemId) != null) {
-                participantDisplayItems.get(participantDisplayItemId).setNick(peerConnectionEvent.getNick());
-                participantsAdapter.notifyDataSetChanged();
-            }
-        } else if (peerConnectionEvent.getPeerConnectionEventType() ==
-            PeerConnectionEvent.PeerConnectionEventType.VIDEO_CHANGE && !isVoiceOnlyCall) {
-            if (participantDisplayItems.get(participantDisplayItemId) != null) {
-                participantDisplayItems.get(participantDisplayItemId).setStreamEnabled(peerConnectionEvent.getChangeValue());
-                participantsAdapter.notifyDataSetChanged();
-            }
-        } else if (peerConnectionEvent.getPeerConnectionEventType() ==
-            PeerConnectionEvent.PeerConnectionEventType.AUDIO_CHANGE) {
-            if (participantDisplayItems.get(participantDisplayItemId) != null) {
-                participantDisplayItems.get(participantDisplayItemId).setAudioEnabled(peerConnectionEvent.getChangeValue());
-                participantsAdapter.notifyDataSetChanged();
-            }
         } else if (peerConnectionEvent.getPeerConnectionEventType() ==
             PeerConnectionEvent.PeerConnectionEventType.PUBLISHER_FAILED) {
             setCallState(CallStatus.PUBLISHER_FAILED);
@@ -2176,12 +2184,12 @@ public class CallActivity extends CallBaseActivity {
     }
 
     private void startSendingNick() {
-        DataChannelMessageNick dataChannelMessage = new DataChannelMessageNick();
+        DataChannelMessage dataChannelMessage = new DataChannelMessage();
         dataChannelMessage.setType("nickChanged");
-        HashMap<String, String> nickChangedPayload = new HashMap<>();
+        Map<String, String> nickChangedPayload = new HashMap<>();
         nickChangedPayload.put("userid", conversationUser.getUserId());
         nickChangedPayload.put("name", conversationUser.getDisplayName());
-        dataChannelMessage.setPayload(nickChangedPayload);
+        dataChannelMessage.setPayloadMap(nickChangedPayload);
         for (PeerConnectionWrapper peerConnectionWrapper : peerConnectionWrapperList) {
             if (peerConnectionWrapper.isMCUPublisher()) {
                 Observable
@@ -2196,7 +2204,7 @@ public class CallActivity extends CallBaseActivity {
 
                         @Override
                         public void onNext(@io.reactivex.annotations.NonNull Long aLong) {
-                            peerConnectionWrapper.sendNickChannelData(dataChannelMessage);
+                            peerConnectionWrapper.sendChannelData(dataChannelMessage);
                         }
 
                         @Override
@@ -2265,7 +2273,7 @@ public class CallActivity extends CallBaseActivity {
         if (hasExternalSignalingServer) {
             nick = webSocketClient.getDisplayNameForSession(session);
         } else {
-            nick = peerConnectionWrapper != null ? peerConnectionWrapper.getNick() : "";
+            nick = offerAnswerNickProviders.get(session) != null ? offerAnswerNickProviders.get(session).getNick() : "";
         }
 
         String userId4Usage = userId;
@@ -2278,11 +2286,14 @@ public class CallActivity extends CallBaseActivity {
             }
         }
 
+        String defaultGuestNick = getResources().getString(R.string.nc_nick_guest);
+
         ParticipantDisplayItem participantDisplayItem = new ParticipantDisplayItem(baseUrl,
                                                                                    userId4Usage,
                                                                                    session,
                                                                                    connected,
                                                                                    nick,
+                                                                                   defaultGuestNick,
                                                                                    mediaStream,
                                                                                    videoStreamType,
                                                                                    videoStreamEnabled,
@@ -2559,6 +2570,47 @@ public class CallActivity extends CallBaseActivity {
         }
     }
 
+    private static class OfferAnswerNickProvider {
+
+        private class WebRtcMessageListener implements SignalingMessageReceiver.WebRtcMessageListener {
+
+            @Override
+            public void onOffer(String sdp, String nick) {
+                (OfferAnswerNickProvider.this).nick = nick;
+            }
+
+            @Override
+            public void onAnswer(String sdp, String nick) {
+                (OfferAnswerNickProvider.this).nick = nick;
+            }
+
+            @Override
+            public void onCandidate(String sdpMid, int sdpMLineIndex, String sdp) {
+            }
+
+            @Override
+            public void onEndOfCandidates() {
+            }
+        }
+
+        private final WebRtcMessageListener videoWebRtcMessageListener = new WebRtcMessageListener();
+        private final WebRtcMessageListener screenWebRtcMessageListener = new WebRtcMessageListener();
+
+        private String nick;
+
+        public WebRtcMessageListener getVideoWebRtcMessageListener() {
+            return videoWebRtcMessageListener;
+        }
+
+        public WebRtcMessageListener getScreenWebRtcMessageListener() {
+            return screenWebRtcMessageListener;
+        }
+
+        public String getNick() {
+            return nick;
+        }
+    }
+
     private class CallActivityCallParticipantMessageListener implements SignalingMessageReceiver.CallParticipantMessageListener {
 
         private final String sessionId;
@@ -2573,6 +2625,66 @@ public class CallActivity extends CallBaseActivity {
         }
     }
 
+    private class CallActivityDataChannelMessageListener implements PeerConnectionWrapper.DataChannelMessageListener {
+
+        private final String participantDisplayItemId;
+
+        private CallActivityDataChannelMessageListener(String sessionId) {
+            // DataChannel messages are sent only in video peers, so the listener only acts on the "video" items.
+            this.participantDisplayItemId = sessionId + "-video";
+        }
+
+        @Override
+        public void onAudioOn() {
+            runOnUiThread(() -> {
+                if (participantDisplayItems.get(participantDisplayItemId) != null) {
+                    participantDisplayItems.get(participantDisplayItemId).setAudioEnabled(true);
+                    participantsAdapter.notifyDataSetChanged();
+                }
+            });
+        }
+
+        @Override
+        public void onAudioOff() {
+            runOnUiThread(() -> {
+                if (participantDisplayItems.get(participantDisplayItemId) != null) {
+                    participantDisplayItems.get(participantDisplayItemId).setAudioEnabled(false);
+                    participantsAdapter.notifyDataSetChanged();
+                }
+            });
+        }
+
+        @Override
+        public void onVideoOn() {
+            runOnUiThread(() -> {
+                if (participantDisplayItems.get(participantDisplayItemId) != null) {
+                    participantDisplayItems.get(participantDisplayItemId).setStreamEnabled(true);
+                    participantsAdapter.notifyDataSetChanged();
+                }
+            });
+        }
+
+        @Override
+        public void onVideoOff() {
+            runOnUiThread(() -> {
+                if (participantDisplayItems.get(participantDisplayItemId) != null) {
+                    participantDisplayItems.get(participantDisplayItemId).setStreamEnabled(false);
+                    participantsAdapter.notifyDataSetChanged();
+                }
+            });
+        }
+
+        @Override
+        public void onNickChanged(String nick) {
+            runOnUiThread(() -> {
+                if (participantDisplayItems.get(participantDisplayItemId) != null) {
+                    participantDisplayItems.get(participantDisplayItemId).setNick(nick);
+                    participantsAdapter.notifyDataSetChanged();
+                }
+            });
+        }
+    }
+
     private class InternalSignalingMessageSender implements SignalingMessageSender {
 
         @Override

+ 8 - 2
app/src/main/java/com/nextcloud/talk/adapters/ParticipantDisplayItem.java

@@ -13,6 +13,7 @@ public class ParticipantDisplayItem {
     private String session;
     private boolean connected;
     private String nick;
+    private final String defaultGuestNick;
     private String urlForAvatar;
     private MediaStream mediaStream;
     private String streamType;
@@ -20,12 +21,13 @@ public class ParticipantDisplayItem {
     private EglBase rootEglBase;
     private boolean isAudioEnabled;
 
-    public ParticipantDisplayItem(String baseUrl, String userId, String session, boolean connected, String nick, MediaStream mediaStream, String streamType, boolean streamEnabled, EglBase rootEglBase) {
+    public ParticipantDisplayItem(String baseUrl, String userId, String session, boolean connected, String nick, String defaultGuestNick, MediaStream mediaStream, String streamType, boolean streamEnabled, EglBase rootEglBase) {
         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;
@@ -61,6 +63,10 @@ public class ParticipantDisplayItem {
     }
 
     public String getNick() {
+        if (TextUtils.isEmpty(userId) && TextUtils.isEmpty(nick)) {
+            return defaultGuestNick;
+        }
+
         return nick;
     }
 
@@ -78,7 +84,7 @@ public class ParticipantDisplayItem {
         if (!TextUtils.isEmpty(userId)) {
             urlForAvatar = ApiUtils.getUrlForAvatar(baseUrl, userId, true);
         } else {
-            urlForAvatar = ApiUtils.getUrlForGuestAvatar(baseUrl, nick, true);
+            urlForAvatar = ApiUtils.getUrlForGuestAvatar(baseUrl, getNick(), true);
         }
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/events/PeerConnectionEvent.java

@@ -120,6 +120,6 @@ public class PeerConnectionEvent {
     }
 
     public enum PeerConnectionEventType {
-        PEER_CONNECTED, PEER_DISCONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE, PUBLISHER_FAILED
+        PEER_CONNECTED, PEER_DISCONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, PUBLISHER_FAILED
     }
 }

+ 7 - 2
app/src/main/java/com/nextcloud/talk/models/json/signaling/DataChannelMessage.kt

@@ -34,10 +34,15 @@ import kotlinx.android.parcel.TypeParceler
 data class DataChannelMessage(
     @JsonField(name = ["type"])
     var type: String? = null,
+    /** Can be String or Map<String, String>
+     *  Use only for received messages */
     @JsonField(name = ["payload"])
-    var payload: Any? = null
+    var payload: Any? = null,
+    /** Use only to send messages */
+    @JsonField(name = ["payload"])
+    var payloadMap: Map<String, String>? = null
 ) : Parcelable {
     // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
-    constructor() : this(null, null)
+    constructor() : this(null, null, null)
     constructor(type: String) : this(type, null)
 }

+ 0 - 40
app/src/main/java/com/nextcloud/talk/models/json/signaling/DataChannelMessageNick.kt

@@ -1,40 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.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.models.json.signaling
-
-import android.os.Parcelable
-import com.bluelinelabs.logansquare.annotation.JsonField
-import com.bluelinelabs.logansquare.annotation.JsonObject
-import java.util.HashMap
-import kotlinx.android.parcel.Parcelize
-
-@Parcelize
-@JsonObject
-data class DataChannelMessageNick(
-    @JsonField(name = ["type"])
-    var type: String? = null,
-    @JsonField(name = ["payload"])
-    var payload: HashMap<String, String>? = null
-) : Parcelable {
-    // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
-    constructor() : this(null, null)
-}

+ 77 - 0
app/src/main/java/com/nextcloud/talk/webrtc/DataChannelMessageNotifier.java

@@ -0,0 +1,77 @@
+/*
+ * 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.webrtc;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Helper class to register and notify DataChannelMessageListeners.
+ *
+ * This class is only meant for internal use by PeerConnectionWrapper; listeners must register themselves against
+ * a PeerConnectionWrapper rather than against a DataChannelMessageNotifier.
+ */
+public class DataChannelMessageNotifier {
+
+    private final Set<PeerConnectionWrapper.DataChannelMessageListener> dataChannelMessageListeners = new LinkedHashSet<>();
+
+    public synchronized void addListener(PeerConnectionWrapper.DataChannelMessageListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("DataChannelMessageListener can not be null");
+        }
+
+        dataChannelMessageListeners.add(listener);
+    }
+
+    public synchronized void removeListener(PeerConnectionWrapper.DataChannelMessageListener listener) {
+        dataChannelMessageListeners.remove(listener);
+    }
+
+    public synchronized void notifyAudioOn() {
+        for (PeerConnectionWrapper.DataChannelMessageListener listener : new ArrayList<>(dataChannelMessageListeners)) {
+            listener.onAudioOn();
+        }
+    }
+
+    public synchronized void notifyAudioOff() {
+        for (PeerConnectionWrapper.DataChannelMessageListener listener : new ArrayList<>(dataChannelMessageListeners)) {
+            listener.onAudioOff();
+        }
+    }
+
+    public synchronized void notifyVideoOn() {
+        for (PeerConnectionWrapper.DataChannelMessageListener listener : new ArrayList<>(dataChannelMessageListeners)) {
+            listener.onVideoOn();
+        }
+    }
+
+    public synchronized void notifyVideoOff() {
+        for (PeerConnectionWrapper.DataChannelMessageListener listener : new ArrayList<>(dataChannelMessageListeners)) {
+            listener.onVideoOff();
+        }
+    }
+
+    public synchronized void notifyNickChanged(String nick) {
+        for (PeerConnectionWrapper.DataChannelMessageListener listener : new ArrayList<>(dataChannelMessageListeners)) {
+            listener.onNickChanged(nick);
+        }
+    }
+}

+ 1 - 2
app/src/main/java/com/nextcloud/talk/webrtc/MagicWebSocketInstance.java

@@ -25,7 +25,6 @@ import android.text.TextUtils;
 import android.util.Log;
 
 import com.bluelinelabs.logansquare.LoganSquare;
-import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.data.user.model.User;
 import com.nextcloud.talk.events.NetworkEvent;
@@ -384,7 +383,7 @@ public class MagicWebSocketInstance extends WebSocketListener {
             }
         }
 
-        return NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_nick_guest);
+        return "";
     }
 
     public String getUserIdForSession(String session) {

+ 82 - 68
app/src/main/java/com/nextcloud/talk/webrtc/PeerConnectionWrapper.java

@@ -24,16 +24,13 @@
 package com.nextcloud.talk.webrtc;
 
 import android.content.Context;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.bluelinelabs.logansquare.LoganSquare;
-import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.events.MediaStreamEvent;
 import com.nextcloud.talk.events.PeerConnectionEvent;
 import com.nextcloud.talk.models.json.signaling.DataChannelMessage;
-import com.nextcloud.talk.models.json.signaling.DataChannelMessageNick;
 import com.nextcloud.talk.models.json.signaling.NCIceCandidate;
 import com.nextcloud.talk.models.json.signaling.NCMessagePayload;
 import com.nextcloud.talk.models.json.signaling.NCSignalingMessage;
@@ -59,8 +56,8 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 import javax.inject.Inject;
@@ -68,12 +65,26 @@ import javax.inject.Inject;
 import androidx.annotation.Nullable;
 import autodagger.AutoInjector;
 
-import static java.lang.Boolean.FALSE;
-import static java.lang.Boolean.TRUE;
-
 @AutoInjector(NextcloudTalkApplication.class)
 public class PeerConnectionWrapper {
 
+    /**
+     * Listener for data channel messages.
+     *
+     * The messages are bound to a specific peer connection, so each listener is expected to handle messages only for
+     * a single peer connection.
+     *
+     * All methods are called on the so called "signaling" thread of WebRTC, which is an internal thread created by the
+     * WebRTC library and NOT the same thread where signaling messages are received.
+     */
+    public interface DataChannelMessageListener {
+        void onAudioOn();
+        void onAudioOff();
+        void onVideoOn();
+        void onVideoOff();
+        void onNickChanged(String nick);
+    }
+
     private static final String TAG = PeerConnectionWrapper.class.getCanonicalName();
 
     private final SignalingMessageReceiver signalingMessageReceiver;
@@ -81,10 +92,11 @@ public class PeerConnectionWrapper {
 
     private final SignalingMessageSender signalingMessageSender;
 
+    private final DataChannelMessageNotifier dataChannelMessageNotifier = new DataChannelMessageNotifier();
+
     private List<IceCandidate> iceCandidates = new ArrayList<>();
     private PeerConnection peerConnection;
     private String sessionId;
-    private String nick;
     private final MediaConstraints mediaConstraints;
     private DataChannel dataChannel;
     private final MagicSdpObserver magicSdpObserver;
@@ -160,6 +172,21 @@ public class PeerConnectionWrapper {
         }
     }
 
+    /**
+     * Adds a listener for data channel messages.
+     *
+     * A listener is expected to be added only once. If the same listener is added again it will be notified just once.
+     *
+     * @param listener the DataChannelMessageListener
+     */
+    public void addListener(DataChannelMessageListener listener) {
+        dataChannelMessageNotifier.addListener(listener);
+    }
+
+    public void removeListener(DataChannelMessageListener listener) {
+        dataChannelMessageNotifier.removeListener(listener);
+    }
+
     public String getVideoStreamType() {
         return videoStreamType;
     }
@@ -203,18 +230,6 @@ public class PeerConnectionWrapper {
         }
     }
 
-    public void sendNickChannelData(DataChannelMessageNick dataChannelMessage) {
-        ByteBuffer buffer;
-        if (dataChannel != null) {
-            try {
-                buffer = ByteBuffer.wrap(LoganSquare.serialize(dataChannelMessage).getBytes());
-                dataChannel.send(new DataChannel.Buffer(buffer, false));
-            } catch (IOException e) {
-                Log.d(TAG, "Failed to send channel data, attempting regular " + dataChannelMessage);
-            }
-        }
-    }
-
     public void sendChannelData(DataChannelMessage dataChannelMessage) {
         ByteBuffer buffer;
         if (dataChannel != null) {
@@ -235,18 +250,6 @@ public class PeerConnectionWrapper {
         return sessionId;
     }
 
-    public String getNick() {
-        if (!TextUtils.isEmpty(nick)) {
-            return nick;
-        } else {
-            return Objects.requireNonNull(NextcloudTalkApplication.Companion.getSharedApplication()).getString(R.string.nc_nick_guest);
-        }
-    }
-
-    private void setNick(String nick) {
-        this.nick = nick;
-    }
-
     private void sendInitialMediaStatus() {
         if (localStream != null) {
             if (localStream.videoTracks.size() == 1 && localStream.videoTracks.get(0).enabled()) {
@@ -288,16 +291,14 @@ public class PeerConnectionWrapper {
     private class WebRtcMessageListener implements SignalingMessageReceiver.WebRtcMessageListener {
 
         public void onOffer(String sdp, String nick) {
-            onOfferOrAnswer("offer", sdp, nick);
+            onOfferOrAnswer("offer", sdp);
         }
 
         public void onAnswer(String sdp, String nick) {
-            onOfferOrAnswer("answer", sdp, nick);
+            onOfferOrAnswer("answer", sdp);
         }
 
-        private void onOfferOrAnswer(String type, String sdp, String nick) {
-            setNick(nick);
-
+        private void onOfferOrAnswer(String type, String sdp) {
             SessionDescription sessionDescriptionWithPreferredCodec;
 
             boolean isAudio = false;
@@ -350,40 +351,53 @@ public class PeerConnectionWrapper {
             String strData = new String(bytes);
             Log.d(TAG, "Got msg: " + strData + " over " + TAG + " " + sessionId);
 
+            DataChannelMessage dataChannelMessage;
             try {
-                DataChannelMessage dataChannelMessage = LoganSquare.parse(strData, DataChannelMessage.class);
-
-                String internalNick;
-                if ("nickChanged".equals(dataChannelMessage.getType())) {
-                    if (dataChannelMessage.getPayload() instanceof String) {
-                        internalNick = (String) dataChannelMessage.getPayload();
-                        if (!internalNick.equals(nick)) {
-                            setNick(internalNick);
-                            EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                                    .NICK_CHANGE, sessionId, getNick(), null, videoStreamType));
-                        }
-                    } else {
-                        if (dataChannelMessage.getPayload() != null) {
-                            HashMap<String, String> payloadHashMap = (HashMap<String, String>) dataChannelMessage.getPayload();
-                            EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                                    .NICK_CHANGE, sessionId, payloadHashMap.get("name"), null, videoStreamType));
-                        }
-                    }
-                } else if ("audioOn".equals(dataChannelMessage.getType())) {
-                    EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                            .AUDIO_CHANGE, sessionId, null, TRUE, videoStreamType));
-                } else if ("audioOff".equals(dataChannelMessage.getType())) {
-                    EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                            .AUDIO_CHANGE, sessionId, null, FALSE, videoStreamType));
-                } else if ("videoOn".equals(dataChannelMessage.getType())) {
-                    EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                            .VIDEO_CHANGE, sessionId, null, TRUE, videoStreamType));
-                } else if ("videoOff".equals(dataChannelMessage.getType())) {
-                    EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
-                            .VIDEO_CHANGE, sessionId, null, FALSE, videoStreamType));
-                }
+                dataChannelMessage = LoganSquare.parse(strData, DataChannelMessage.class);
             } catch (IOException e) {
                 Log.d(TAG, "Failed to parse data channel message");
+
+                return;
+            }
+
+            if ("nickChanged".equals(dataChannelMessage.getType())) {
+                String nick = null;
+                if (dataChannelMessage.getPayload() instanceof String) {
+                    nick = (String) dataChannelMessage.getPayload();
+                } else if (dataChannelMessage.getPayload() instanceof Map) {
+                    Map<String, String> payloadMap = (Map<String, String>) dataChannelMessage.getPayload();
+                    nick = payloadMap.get("name");
+                }
+
+                if (nick != null) {
+                    dataChannelMessageNotifier.notifyNickChanged(nick);
+                }
+
+                return;
+            }
+
+            if ("audioOn".equals(dataChannelMessage.getType())) {
+                dataChannelMessageNotifier.notifyAudioOn();
+
+                return;
+            }
+
+            if ("audioOff".equals(dataChannelMessage.getType())) {
+                dataChannelMessageNotifier.notifyAudioOff();
+
+                return;
+            }
+
+            if ("videoOn".equals(dataChannelMessage.getType())) {
+                dataChannelMessageNotifier.notifyVideoOn();
+
+                return;
+            }
+
+            if ("videoOff".equals(dataChannelMessage.getType())) {
+                dataChannelMessageNotifier.notifyVideoOff();
+
+                return;
             }
         }
     }