CallParticipantModel.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Nextcloud Talk application
  3. *
  4. * @author Daniel Calviño Sánchez
  5. * Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package com.nextcloud.talk.call;
  21. import android.os.Handler;
  22. import org.webrtc.MediaStream;
  23. import org.webrtc.PeerConnection;
  24. import java.util.Objects;
  25. /**
  26. * Read-only data model for (remote) call participants.
  27. *
  28. * If the hand was never raised null is returned by "getRaisedHand()". Otherwise a RaisedHand object is returned with
  29. * the current state (raised or not) and the timestamp when the raised hand state last changed.
  30. *
  31. * The received audio and video are available only if the participant is sending them and also has them enabled.
  32. * Before a connection is established it is not known whether audio and video are available or not, so null is returned
  33. * in that case (therefore it should not be autoboxed to a plain boolean without checking that).
  34. *
  35. * Audio and video in screen shares, on the other hand, are always seen as available.
  36. *
  37. * Clients of the model can observe it with CallParticipantModel.Observer to be notified when any value changes.
  38. * Getters called after receiving a notification are guaranteed to provide at least the value that triggered the
  39. * notification, but it may return even a more up to date one (so getting the value again on the following
  40. * notification may return the same value as before).
  41. *
  42. * Besides onChange(), which notifies about changes in the model values, CallParticipantModel.Observer provides
  43. * additional methods to be notified about one-time events that are not reflected in the model values, like reactions.
  44. */
  45. public class CallParticipantModel {
  46. protected final CallParticipantModelNotifier callParticipantModelNotifier = new CallParticipantModelNotifier();
  47. protected final String sessionId;
  48. protected Data<String> userId;
  49. protected Data<String> nick;
  50. protected Data<Boolean> internal;
  51. protected Data<RaisedHand> raisedHand;
  52. protected Data<PeerConnection.IceConnectionState> iceConnectionState;
  53. protected Data<MediaStream> mediaStream;
  54. protected Data<Boolean> audioAvailable;
  55. protected Data<Boolean> videoAvailable;
  56. protected Data<PeerConnection.IceConnectionState> screenIceConnectionState;
  57. protected Data<MediaStream> screenMediaStream;
  58. public interface Observer {
  59. void onChange();
  60. void onReaction(String reaction);
  61. }
  62. protected class Data<T> {
  63. private T value;
  64. public T getValue() {
  65. return value;
  66. }
  67. public void setValue(T value) {
  68. if (Objects.equals(this.value, value)) {
  69. return;
  70. }
  71. this.value = value;
  72. callParticipantModelNotifier.notifyChange();
  73. }
  74. }
  75. public CallParticipantModel(String sessionId) {
  76. this.sessionId = sessionId;
  77. this.userId = new Data<>();
  78. this.nick = new Data<>();
  79. this.internal = new Data<>();
  80. this.raisedHand = new Data<>();
  81. this.iceConnectionState = new Data<>();
  82. this.mediaStream = new Data<>();
  83. this.audioAvailable = new Data<>();
  84. this.videoAvailable = new Data<>();
  85. this.screenIceConnectionState = new Data<>();
  86. this.screenMediaStream = new Data<>();
  87. }
  88. public String getSessionId() {
  89. return sessionId;
  90. }
  91. public String getUserId() {
  92. return userId.getValue();
  93. }
  94. public String getNick() {
  95. return nick.getValue();
  96. }
  97. public Boolean isInternal() {
  98. return internal.getValue();
  99. }
  100. public RaisedHand getRaisedHand() {
  101. return raisedHand.getValue();
  102. }
  103. public PeerConnection.IceConnectionState getIceConnectionState() {
  104. return iceConnectionState.getValue();
  105. }
  106. public MediaStream getMediaStream() {
  107. return mediaStream.getValue();
  108. }
  109. public Boolean isAudioAvailable() {
  110. return audioAvailable.getValue();
  111. }
  112. public Boolean isVideoAvailable() {
  113. return videoAvailable.getValue();
  114. }
  115. public PeerConnection.IceConnectionState getScreenIceConnectionState() {
  116. return screenIceConnectionState.getValue();
  117. }
  118. public MediaStream getScreenMediaStream() {
  119. return screenMediaStream.getValue();
  120. }
  121. /**
  122. * Adds an Observer to be notified when any value changes.
  123. *
  124. * @param observer the Observer
  125. * @see CallParticipantModel#addObserver(Observer, Handler)
  126. */
  127. public void addObserver(Observer observer) {
  128. addObserver(observer, null);
  129. }
  130. /**
  131. * Adds an observer to be notified when any value changes.
  132. *
  133. * The observer will be notified on the thread associated to the given handler. If no handler is given the
  134. * observer will be immediately notified on the same thread that changed the value; the observer will be
  135. * immediately notified too if the thread of the handler is the same thread that changed the value.
  136. *
  137. * An observer is expected to be added only once. If the same observer is added again it will be notified just
  138. * once on the thread of the last handler.
  139. *
  140. * @param observer the Observer
  141. * @param handler a Handler for the thread to be notified on
  142. */
  143. public void addObserver(Observer observer, Handler handler) {
  144. callParticipantModelNotifier.addObserver(observer, handler);
  145. }
  146. public void removeObserver(Observer observer) {
  147. callParticipantModelNotifier.removeObserver(observer);
  148. }
  149. }