David Zhao

Moved callbacks to Room, removed Remote*Track classes

@@ -137,7 +137,7 @@ constructor( @@ -137,7 +137,7 @@ constructor(
137 interface Listener { 137 interface Listener {
138 fun onJoin(response: LivekitRtc.JoinResponse) 138 fun onJoin(response: LivekitRtc.JoinResponse)
139 fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>) 139 fun onAddTrack(track: MediaStreamTrack, streams: Array<out MediaStream>)
140 - fun onPublishLocalTrack(cid: String, track: LivekitModels.TrackInfo) 140 +// fun onPublishLocalTrack(cid: String, track: LivekitModels.TrackInfo)
141 fun onAddDataChannel(channel: DataChannel) 141 fun onAddDataChannel(channel: DataChannel)
142 fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>) 142 fun onUpdateParticipants(updates: List<LivekitModels.ParticipantInfo>)
143 fun onUpdateSpeakers(speakers: List<LivekitRtc.SpeakerInfo>) 143 fun onUpdateSpeakers(speakers: List<LivekitRtc.SpeakerInfo>)
@@ -267,8 +267,7 @@ constructor( @@ -267,8 +267,7 @@ constructor(
267 return 267 return
268 } 268 }
269 cont.resume(response.track) 269 cont.resume(response.track)
270 - listener?.onPublishLocalTrack(cid, track)  
271 - 270 +// listener?.onPublishLocalTrack(cid, track)
272 } 271 }
273 272
274 override fun onParticipantUpdate(updates: List<LivekitModels.ParticipantInfo>) { 273 override fun onParticipantUpdate(updates: List<LivekitModels.ParticipantInfo>) {
@@ -9,10 +9,14 @@ import io.livekit.android.ConnectOptions @@ -9,10 +9,14 @@ import io.livekit.android.ConnectOptions
9 import io.livekit.android.room.participant.LocalParticipant 9 import io.livekit.android.room.participant.LocalParticipant
10 import io.livekit.android.room.participant.Participant 10 import io.livekit.android.room.participant.Participant
11 import io.livekit.android.room.participant.RemoteParticipant 11 import io.livekit.android.room.participant.RemoteParticipant
  12 +import io.livekit.android.room.track.DataTrack
  13 +import io.livekit.android.room.track.Track
  14 +import io.livekit.android.room.track.TrackPublication
12 import io.livekit.android.room.util.unpackedTrackLabel 15 import io.livekit.android.room.util.unpackedTrackLabel
13 import livekit.LivekitModels 16 import livekit.LivekitModels
14 import livekit.LivekitRtc 17 import livekit.LivekitRtc
15 import org.webrtc.* 18 import org.webrtc.*
  19 +import java.nio.ByteBuffer
16 import kotlin.coroutines.Continuation 20 import kotlin.coroutines.Continuation
17 import kotlin.coroutines.resume 21 import kotlin.coroutines.resume
18 import kotlin.coroutines.suspendCoroutine 22 import kotlin.coroutines.suspendCoroutine
@@ -45,7 +49,7 @@ constructor( @@ -45,7 +49,7 @@ constructor(
45 private set 49 private set
46 var state: State = State.DISCONNECTED 50 var state: State = State.DISCONNECTED
47 private set 51 private set
48 - var localParticipant: LocalParticipant? = null 52 + lateinit var localParticipant: LocalParticipant
49 private set 53 private set
50 private val mutableRemoteParticipants = mutableMapOf<String, RemoteParticipant>() 54 private val mutableRemoteParticipants = mutableMapOf<String, RemoteParticipant>()
51 val remoteParticipants: Map<String, RemoteParticipant> 55 val remoteParticipants: Map<String, RemoteParticipant>
@@ -57,10 +61,6 @@ constructor( @@ -57,10 +61,6 @@ constructor(
57 61
58 private var connectContinuation: Continuation<Unit>? = null 62 private var connectContinuation: Continuation<Unit>? = null
59 suspend fun connect(url: String, token: String) { 63 suspend fun connect(url: String, token: String) {
60 - if (localParticipant != null) {  
61 - Timber.d { "Attempting to connect to room when already connected." }  
62 - return  
63 - }  
64 engine.join(url, token) 64 engine.join(url, token)
65 65
66 return suspendCoroutine { connectContinuation = it } 66 return suspendCoroutine { connectContinuation = it }
@@ -120,7 +120,7 @@ constructor( @@ -120,7 +120,7 @@ constructor(
120 } 120 }
121 } 121 }
122 122
123 - if (localParticipant != null && !seenSids.contains(localParticipant.sid)) { 123 + if (!seenSids.contains(localParticipant.sid)) {
124 localParticipant.audioLevel = 0.0f 124 localParticipant.audioLevel = 0.0f
125 } 125 }
126 remoteParticipants.values 126 remoteParticipants.values
@@ -140,22 +140,6 @@ constructor( @@ -140,22 +140,6 @@ constructor(
140 fun create(connectOptions: ConnectOptions): Room 140 fun create(connectOptions: ConnectOptions): Room
141 } 141 }
142 142
143 - /**  
144 - * Room Listener, this class provides callbacks that clients should override.  
145 - *  
146 - */  
147 - interface Listener {  
148 - fun onConnect(room: Room) {}  
149 - fun onDisconnect(room: Room, error: Exception?) {}  
150 - fun onParticipantConnected(room: Room, participant: RemoteParticipant) {}  
151 - fun onParticipantDisconnected(room: Room, participant: RemoteParticipant) {}  
152 - fun onFailedToConnect(room: Room, error: Exception) {}  
153 - fun onReconnecting(room: Room, error: Exception) {}  
154 - fun onReconnect(room: Room) {}  
155 - fun onMetadataChanged(room: Room, Participant: Participant, prevMetadata: String?) {}  
156 - fun onActiveSpeakersChanged(speakers: List<Participant>, room: Room) {}  
157 - }  
158 -  
159 //----------------------------------- RTCEngine.Listener ------------------------------------// 143 //----------------------------------- RTCEngine.Listener ------------------------------------//
160 /** 144 /**
161 * @suppress 145 * @suppress
@@ -163,25 +147,18 @@ constructor( @@ -163,25 +147,18 @@ constructor(
163 override fun onJoin(response: LivekitRtc.JoinResponse) { 147 override fun onJoin(response: LivekitRtc.JoinResponse) {
164 Timber.v { "engine did join, version: ${response.serverVersion}" } 148 Timber.v { "engine did join, version: ${response.serverVersion}" }
165 149
166 - try {  
167 - val serverVersion = Semver(response.serverVersion)  
168 - if (serverVersion.major == 0 && serverVersion.minor < 5) {  
169 - Timber.e { "This version of livekit requires server version >= 0.5.x" }  
170 - return  
171 - }  
172 - } catch (e: Exception) {  
173 - Timber.e { "Unable to parse server version!" }  
174 - return  
175 - }  
176 state = State.CONNECTED 150 state = State.CONNECTED
177 sid = Sid(response.room.sid) 151 sid = Sid(response.room.sid)
178 name = response.room.name 152 name = response.room.name
179 153
180 - if (response.hasParticipant()) { 154 + if (!response.hasParticipant()) {
  155 + listener?.onFailedToConnect(this, RoomException.ConnectException("server didn't return any participants"))
  156 + return
  157 + }
  158 +
181 val lp = LocalParticipant(response.participant, engine) 159 val lp = LocalParticipant(response.participant, engine)
182 lp.listener = this 160 lp.listener = this
183 localParticipant = lp 161 localParticipant = lp
184 - }  
185 if (response.otherParticipantsList.isNotEmpty()) { 162 if (response.otherParticipantsList.isNotEmpty()) {
186 response.otherParticipantsList.forEach { 163 response.otherParticipantsList.forEach {
187 getOrCreateRemoteParticipant(it.sid, it) 164 getOrCreateRemoteParticipant(it.sid, it)
@@ -190,7 +167,6 @@ constructor( @@ -190,7 +167,6 @@ constructor(
190 167
191 connectContinuation?.resume(Unit) 168 connectContinuation?.resume(Unit)
192 connectContinuation = null 169 connectContinuation = null
193 - listener?.onConnect(this)  
194 } 170 }
195 171
196 /** 172 /**
@@ -218,11 +194,6 @@ constructor( @@ -218,11 +194,6 @@ constructor(
218 participant.addSubscribedDataTrack(channel, trackSid, name) 194 participant.addSubscribedDataTrack(channel, trackSid, name)
219 } 195 }
220 196
221 - /**  
222 - * @suppress  
223 - */  
224 - override fun onPublishLocalTrack(cid: String, track: LivekitModels.TrackInfo) {  
225 - }  
226 197
227 /** 198 /**
228 * @suppress 199 * @suppress
@@ -231,8 +202,9 @@ constructor( @@ -231,8 +202,9 @@ constructor(
231 for (info in updates) { 202 for (info in updates) {
232 val participantSid = info.sid 203 val participantSid = info.sid
233 204
234 - if(localParticipant?.sid == participantSid) {  
235 - localParticipant?.updateFromInfo(info) 205 + if(localParticipant.sid == participantSid) {
  206 + localParticipant.updateFromInfo(info)
  207 + continue
236 } 208 }
237 209
238 val isNewParticipant = remoteParticipants.contains(participantSid) 210 val isNewParticipant = remoteParticipants.contains(participantSid)
@@ -272,12 +244,48 @@ constructor( @@ -272,12 +244,48 @@ constructor(
272 244
273 //------------------------------- RemoteParticipant.Listener --------------------------------// 245 //------------------------------- RemoteParticipant.Listener --------------------------------//
274 /** 246 /**
  247 + * This is called for both Local and Remote participants
275 * @suppress 248 * @suppress
276 */ 249 */
277 override fun onMetadataChanged(participant: Participant, prevMetadata: String?) { 250 override fun onMetadataChanged(participant: Participant, prevMetadata: String?) {
278 - listener?.onMetadataChanged(this, participant, prevMetadata) 251 + listener?.onMetadataChanged(participant, prevMetadata, this)
  252 + }
  253 +
  254 + override fun onTrackPublished(publication: TrackPublication, participant: RemoteParticipant) {
  255 + listener?.onTrackPublished(publication, participant, this)
  256 + }
  257 +
  258 + override fun onTrackUnpublished(publication: TrackPublication, participant: RemoteParticipant) {
  259 + listener?.onTrackUnpublished(publication, participant, this)
  260 + }
  261 +
  262 + override fun onTrackSubscribed(track: Track, publication: TrackPublication, participant: RemoteParticipant) {
  263 + listener?.onTrackSubscribed(track, publication, participant, this)
  264 + }
  265 +
  266 + override fun onTrackSubscriptionFailed(
  267 + sid: String,
  268 + exception: Exception,
  269 + participant: RemoteParticipant
  270 + ) {
  271 + listener?.onTrackSubscriptionFailed(sid, exception, participant, this)
  272 + }
  273 +
  274 + override fun onTrackUnsubscribed(
  275 + track: Track,
  276 + publication: TrackPublication,
  277 + participant: RemoteParticipant
  278 + ) {
  279 + listener?.onTrackUnsubscribed(track, publication, participant, this)
279 } 280 }
280 281
  282 + override fun onDataReceived(
  283 + data: ByteBuffer,
  284 + dataTrack: DataTrack,
  285 + participant: RemoteParticipant
  286 + ) {
  287 + listener?.onDataReceived(data, dataTrack, participant, this)
  288 + }
281 289
282 /** 290 /**
283 * @suppress 291 * @suppress
@@ -288,4 +296,86 @@ constructor( @@ -288,4 +296,86 @@ constructor(
288 viewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT) 296 viewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT)
289 viewRenderer.setEnableHardwareScaler(false /* enabled */); 297 viewRenderer.setEnableHardwareScaler(false /* enabled */);
290 } 298 }
  299 +
  300 + /**
  301 + * Room Listener, this class provides callbacks that clients should override.
  302 + *
  303 + */
  304 + interface Listener {
  305 + /**
  306 + * Disconnected from room
  307 + */
  308 + fun onDisconnect(room: Room, error: Exception?) {}
  309 +
  310 + /**
  311 + * When a [RemoteParticipant] joins after the local participant. It will not emit events
  312 + * for participants that are already in the room
  313 + */
  314 + fun onParticipantConnected(room: Room, participant: RemoteParticipant) {}
  315 +
  316 + /**
  317 + * When a [RemoteParticipant] leaves after the local participant has joined.
  318 + */
  319 + fun onParticipantDisconnected(room: Room, participant: RemoteParticipant) {}
  320 +
  321 + /**
  322 + * Could not connect to the room
  323 + */
  324 + fun onFailedToConnect(room: Room, error: Exception) {}
  325 +// fun onReconnecting(room: Room, error: Exception) {}
  326 +// fun onReconnect(room: Room) {}
  327 +
  328 + /**
  329 + * Active speakers changed. List of speakers are ordered by their audio level. loudest
  330 + * speakers first. This will include the [LocalParticipant] too.
  331 + */
  332 + fun onActiveSpeakersChanged(speakers: List<Participant>, room: Room) {}
  333 +
  334 + // Participant callbacks
  335 + /**
  336 + * Participant metadata is a simple way for app-specific state to be pushed to all users.
  337 + * When RoomService.UpdateParticipantMetadata is called to change a participant's state,
  338 + * this event will be fired for all clients in the room.
  339 + */
  340 + fun onMetadataChanged(Participant: Participant, prevMetadata: String?, room: Room) {}
  341 +
  342 + /**
  343 + * When a new track is published to room after the local participant has joined. It will
  344 + * not fire for tracks that are already published
  345 + */
  346 + fun onTrackPublished(publication: TrackPublication, participant: RemoteParticipant, room: Room) {}
  347 +
  348 + /**
  349 + * A [RemoteParticipant] has unpublished a track
  350 + */
  351 + fun onTrackUnpublished(publication: TrackPublication, participant: RemoteParticipant, room: Room) {}
  352 +
  353 + /**
  354 + * The [LocalParticipant] has subscribed to a new track. This event will always fire as
  355 + * long as new tracks are ready for use.
  356 + */
  357 + fun onTrackSubscribed(track: Track, publication: TrackPublication, participant: RemoteParticipant, room: Room) {}
  358 +
  359 + /**
  360 + * Could not subscribe to a track
  361 + */
  362 + fun onTrackSubscriptionFailed(sid: String, exception: Exception, participant: RemoteParticipant, room: Room) {}
  363 +
  364 + /**
  365 + * A subscribed track is no longer available. Clients should listen to this event and ensure
  366 + * the track removes all renderers
  367 + */
  368 + fun onTrackUnsubscribed(track: Track, publications: TrackPublication, participant: RemoteParticipant, room: Room) {}
  369 +
  370 + /**
  371 + * Message received over a [DataTrack]
  372 + */
  373 + fun onDataReceived(data: ByteBuffer, dataTrack: DataTrack, participant: RemoteParticipant, room: Room) {}
  374 + }
  375 +}
  376 +
  377 +sealed class RoomException(message: String? = null, cause: Throwable? = null) :
  378 + Exception(message, cause) {
  379 + class ConnectException(message: String? = null, cause: Throwable? = null) :
  380 + RoomException(message, cause)
291 } 381 }
@@ -27,6 +27,8 @@ open class Participant(var sid: String, identity: String? = null) { @@ -27,6 +27,8 @@ open class Participant(var sid: String, identity: String? = null) {
27 * @suppress 27 * @suppress
28 */ 28 */
29 fun addTrackPublication(publication: TrackPublication) { 29 fun addTrackPublication(publication: TrackPublication) {
  30 + val track = publication.track
  31 + track?.sid = publication.sid
30 tracks[publication.sid] = publication 32 tracks[publication.sid] = publication
31 when (publication.kind) { 33 when (publication.kind) {
32 LivekitModels.TrackType.AUDIO -> audioTracks[publication.sid] = publication 34 LivekitModels.TrackType.AUDIO -> audioTracks[publication.sid] = publication
@@ -15,7 +15,7 @@ import java.nio.ByteBuffer @@ -15,7 +15,7 @@ import java.nio.ByteBuffer
15 15
16 class RemoteParticipant( 16 class RemoteParticipant(
17 sid: String, name: String? = null 17 sid: String, name: String? = null
18 -) : Participant(sid, name), RemoteDataTrack.Listener { 18 +) : Participant(sid, name) {
19 /** 19 /**
20 * @suppress 20 * @suppress
21 */ 21 */
@@ -31,8 +31,7 @@ class RemoteParticipant( @@ -31,8 +31,7 @@ class RemoteParticipant(
31 31
32 private val coroutineScope = CloseableCoroutineScope(SupervisorJob()) 32 private val coroutineScope = CloseableCoroutineScope(SupervisorJob())
33 33
34 - fun getTrackPublication(sid: String): TrackPublication? =  
35 - tracks[sid] 34 + fun getTrackPublication(sid: String): TrackPublication? = tracks[sid]
36 35
37 /** 36 /**
38 * @suppress 37 * @suppress
@@ -62,7 +61,7 @@ class RemoteParticipant( @@ -62,7 +61,7 @@ class RemoteParticipant(
62 61
63 if (hadInfo) { 62 if (hadInfo) {
64 for (publication in newTrackPublications.values) { 63 for (publication in newTrackPublications.values) {
65 - listener?.onPublish(publication, this) 64 + listener?.onTrackPublished(publication, this)
66 } 65 }
67 } 66 }
68 67
@@ -79,8 +78,8 @@ class RemoteParticipant( @@ -79,8 +78,8 @@ class RemoteParticipant(
79 fun addSubscribedMediaTrack(mediaTrack: MediaStreamTrack, sid: String, triesLeft: Int = 20) { 78 fun addSubscribedMediaTrack(mediaTrack: MediaStreamTrack, sid: String, triesLeft: Int = 20) {
80 val publication = getTrackPublication(sid) 79 val publication = getTrackPublication(sid)
81 val track: Track = when (val kind = mediaTrack.kind()) { 80 val track: Track = when (val kind = mediaTrack.kind()) {
82 - KIND_AUDIO -> RemoteAudioTrack(sid = sid, mediaTrack = mediaTrack as AudioTrack, name = "")  
83 - KIND_VIDEO -> RemoteVideoTrack(sid = sid, mediaTrack = mediaTrack as VideoTrack, name = "") 81 + KIND_AUDIO -> AudioTrack(rtcTrack = mediaTrack as AudioTrack, name = "")
  82 + KIND_VIDEO -> VideoTrack(rtcTrack = mediaTrack as VideoTrack, name = "")
84 else -> throw TrackException.InvalidTrackTypeException("invalid track type: $kind") 83 else -> throw TrackException.InvalidTrackTypeException("invalid track type: $kind")
85 } 84 }
86 85
@@ -90,7 +89,7 @@ class RemoteParticipant( @@ -90,7 +89,7 @@ class RemoteParticipant(
90 val exception = TrackException.InvalidTrackStateException(message) 89 val exception = TrackException.InvalidTrackStateException(message)
91 Timber.e { "remote participant ${this.sid} --- $message" } 90 Timber.e { "remote participant ${this.sid} --- $message" }
92 91
93 - listener?.onFailToSubscribe(sid, exception, this) 92 + listener?.onTrackSubscriptionFailed(sid, exception, this)
94 } else { 93 } else {
95 coroutineScope.launch { 94 coroutineScope.launch {
96 delay(150) 95 delay(150)
@@ -100,14 +99,14 @@ class RemoteParticipant( @@ -100,14 +99,14 @@ class RemoteParticipant(
100 return 99 return
101 } 100 }
102 101
103 - val remoteTrack = track as RemoteTrack  
104 publication.track = track 102 publication.track = track
105 track.name = publication.name 103 track.name = publication.name
106 - remoteTrack.sid = publication.sid 104 + track.sid = publication.sid
  105 + addTrackPublication(publication)
107 106
108 // TODO: how does mediatrack send ended event? 107 // TODO: how does mediatrack send ended event?
109 108
110 - listener?.onSubscribe(track, publication, this) 109 + listener?.onTrackSubscribed(track, publication, this)
111 } 110 }
112 111
113 /** 112 /**
@@ -117,20 +116,19 @@ class RemoteParticipant( @@ -117,20 +116,19 @@ class RemoteParticipant(
117 val track = DataTrack(name, dataChannel) 116 val track = DataTrack(name, dataChannel)
118 var publication = getTrackPublication(sid) 117 var publication = getTrackPublication(sid)
119 118
120 - if (publication != null) {  
121 - publication.track = track  
122 - } else { 119 + if (publication == null) {
123 val trackInfo = LivekitModels.TrackInfo.newBuilder() 120 val trackInfo = LivekitModels.TrackInfo.newBuilder()
124 .setSid(sid) 121 .setSid(sid)
125 .setName(name) 122 .setName(name)
126 .setType(LivekitModels.TrackType.DATA) 123 .setType(LivekitModels.TrackType.DATA)
127 .build() 124 .build()
128 - publication = TrackPublication(info = trackInfo, track = track) 125 + publication = TrackPublication(info = trackInfo)
129 addTrackPublication(publication) 126 addTrackPublication(publication)
130 if (hasInfo) { 127 if (hasInfo) {
131 - listener?.onPublish(publication, this) 128 + listener?.onTrackPublished(publication, this)
132 } 129 }
133 } 130 }
  131 + publication.track = track
134 132
135 dataChannel.registerObserver(object : DataChannel.Observer { 133 dataChannel.registerObserver(object : DataChannel.Observer {
136 override fun onBufferedAmountChange(previousAmount: Long) {} 134 override fun onBufferedAmountChange(previousAmount: Long) {}
@@ -139,15 +137,15 @@ class RemoteParticipant( @@ -139,15 +137,15 @@ class RemoteParticipant(
139 val newState = dataChannel.state() 137 val newState = dataChannel.state()
140 if (newState == DataChannel.State.CLOSED) { 138 if (newState == DataChannel.State.CLOSED) {
141 publication.track = null 139 publication.track = null
142 - listener?.onUnsubscribe(track, publication, this@RemoteParticipant) 140 + listener?.onTrackUnsubscribed(track, publication, this@RemoteParticipant)
143 } 141 }
144 } 142 }
145 143
146 override fun onMessage(buffer: DataChannel.Buffer) { 144 override fun onMessage(buffer: DataChannel.Buffer) {
147 - listener?.onReceive(buffer.data, track, this@RemoteParticipant) 145 + listener?.onDataReceived(buffer.data, track, this@RemoteParticipant)
148 } 146 }
149 }) 147 })
150 - listener?.onSubscribe(track, publication, participant = this) 148 + listener?.onTrackSubscribed(track, publication, participant = this)
151 } 149 }
152 150
153 fun unpublishTrack(trackSid: String, sendUnpublish: Boolean = false) { 151 fun unpublishTrack(trackSid: String, sendUnpublish: Boolean = false) {
@@ -162,57 +160,49 @@ class RemoteParticipant( @@ -162,57 +160,49 @@ class RemoteParticipant(
162 val track = publication.track 160 val track = publication.track
163 if (track != null) { 161 if (track != null) {
164 track.stop() 162 track.stop()
165 - listener?.onUnsubscribe(track, publication, this) 163 + listener?.onTrackUnsubscribed(track, publication, this)
166 } 164 }
167 if (sendUnpublish) { 165 if (sendUnpublish) {
168 - listener?.onUnpublish(publication, this) 166 + listener?.onTrackUnpublished(publication, this)
169 } 167 }
170 } 168 }
171 169
172 - override fun onReceiveString(message: String, dataTrack: DataTrack) {  
173 - TODO("Not yet implemented")  
174 - }  
175 -  
176 - override fun onReceiveData(message: DataChannel.Buffer, dataTrack: DataTrack) {  
177 - TODO("Not yet implemented")  
178 - }  
179 -  
180 companion object { 170 companion object {
181 private const val KIND_AUDIO = "audio" 171 private const val KIND_AUDIO = "audio"
182 private const val KIND_VIDEO = "video" 172 private const val KIND_VIDEO = "video"
183 } 173 }
184 174
185 interface Listener: Participant.Listener { 175 interface Listener: Participant.Listener {
186 - fun onPublish(publication: TrackPublication, participant: RemoteParticipant) {}  
187 - fun onUnpublish(publication: TrackPublication, participant: RemoteParticipant) {} 176 + fun onTrackPublished(publication: TrackPublication, participant: RemoteParticipant) {}
  177 + fun onTrackUnpublished(publication: TrackPublication, participant: RemoteParticipant) {}
188 178
189 fun onEnable(publication: TrackPublication, participant: RemoteParticipant) {} 179 fun onEnable(publication: TrackPublication, participant: RemoteParticipant) {}
190 fun onDisable(publication: TrackPublication, participant: RemoteParticipant) {} 180 fun onDisable(publication: TrackPublication, participant: RemoteParticipant) {}
191 181
192 - fun onSubscribe(track: Track, publication: TrackPublication, participant: RemoteParticipant) {}  
193 - fun onFailToSubscribe( 182 + fun onTrackSubscribed(track: Track, publication: TrackPublication, participant: RemoteParticipant) {}
  183 + fun onTrackSubscriptionFailed(
194 sid: String, 184 sid: String,
195 exception: Exception, 185 exception: Exception,
196 participant: RemoteParticipant 186 participant: RemoteParticipant
197 ) { 187 ) {
198 } 188 }
199 189
200 - fun onUnsubscribe( 190 + fun onTrackUnsubscribed(
201 track: Track, 191 track: Track,
202 - publications: TrackPublication, 192 + publication: TrackPublication,
203 participant: RemoteParticipant 193 participant: RemoteParticipant
204 ) { 194 ) {
205 } 195 }
206 196
207 - fun onReceive( 197 + fun onDataReceived(
208 data: ByteBuffer, 198 data: ByteBuffer,
209 dataTrack: DataTrack, 199 dataTrack: DataTrack,
210 participant: RemoteParticipant 200 participant: RemoteParticipant
211 ) { 201 ) {
212 } 202 }
213 203
214 - fun switchedOffVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {}  
215 - fun switchedOnVideo(track: RemoteVideoTrack, participant: RemoteParticipant) {} 204 + fun switchedOffVideo(track: VideoTrack, publication: TrackPublication, participant: RemoteParticipant) {}
  205 + fun switchedOnVideo(track: VideoTrack, publication: TrackPublication, participant: RemoteParticipant) {}
216 } 206 }
217 207
218 } 208 }
@@ -7,8 +7,6 @@ import java.util.* @@ -7,8 +7,6 @@ import java.util.*
7 class LocalDataTrack( 7 class LocalDataTrack(
8 val options: DataTrackOptions 8 val options: DataTrackOptions
9 ) : DataTrack(options.name) { 9 ) : DataTrack(options.name) {
10 - var sid: String? = null  
11 - internal set  
12 var cid: String = UUID.randomUUID().toString() 10 var cid: String = UUID.randomUUID().toString()
13 11
14 fun sendString(message: String) { 12 fun sendString(message: String) {
1 -package io.livekit.android.room.track  
2 -  
3 -class RemoteAudioTrack(  
4 - sid: String,  
5 - playbackEnabled: Boolean = true,  
6 - name: String,  
7 - mediaTrack: org.webrtc.AudioTrack  
8 -) : AudioTrack(name, mediaTrack), RemoteTrack {  
9 -  
10 - override var sid: String = sid  
11 - var playbackEnabled = playbackEnabled  
12 - internal set  
13 -  
14 -}  
1 -package io.livekit.android.room.track  
2 -  
3 -import org.webrtc.DataChannel  
4 -  
5 -class RemoteDataTrack(  
6 - override var sid: String,  
7 - name: String,  
8 - rtcTrack: DataChannel  
9 -) :  
10 - DataTrack(name, rtcTrack),  
11 - RemoteTrack {  
12 -  
13 - var listener: Listener? = null  
14 -  
15 - interface Listener {  
16 - fun onReceiveString(message: String, dataTrack: DataTrack)  
17 - fun onReceiveData(message: DataChannel.Buffer, dataTrack: DataTrack)  
18 - }  
19 -}  
1 -package io.livekit.android.room.track  
2 -  
3 -interface RemoteTrack {  
4 - var sid: String  
5 -}  
1 -package io.livekit.android.room.track  
2 -  
3 -class RemoteVideoTrack(  
4 - override var sid: String,  
5 - var switchedOff: Boolean = false,  
6 - name: String,  
7 - mediaTrack: org.webrtc.VideoTrack  
8 -) : VideoTrack(name, mediaTrack), RemoteTrack  
@@ -10,6 +10,8 @@ open class Track(name: String, kind: LivekitModels.TrackType) { @@ -10,6 +10,8 @@ open class Track(name: String, kind: LivekitModels.TrackType) {
10 var kind = kind 10 var kind = kind
11 internal set 11 internal set
12 var state: State = State.NONE 12 var state: State = State.NONE
  13 + var sid: String? = null
  14 + internal set
13 15
14 enum class State { 16 enum class State {
15 ENDED, LIVE, NONE; 17 ENDED, LIVE, NONE;
@@ -34,10 +34,6 @@ class CallViewModel( @@ -34,10 +34,6 @@ class CallViewModel(
34 token, 34 token,
35 ConnectOptions(false), 35 ConnectOptions(false),
36 object : Room.Listener { 36 object : Room.Listener {
37 - override fun onConnect(room: Room) {  
38 - updateParticipants(room)  
39 - }  
40 -  
41 override fun onDisconnect(room: Room, error: Exception?) { 37 override fun onDisconnect(room: Room, error: Exception?) {
42 } 38 }
43 39
@@ -58,25 +54,15 @@ class CallViewModel( @@ -58,25 +54,15 @@ class CallViewModel(
58 override fun onFailedToConnect(room: Room, error: Exception) { 54 override fun onFailedToConnect(room: Room, error: Exception) {
59 } 55 }
60 56
61 - override fun onReconnecting(room: Room, error: Exception) {  
62 - }  
63 -  
64 - override fun onReconnect(room: Room) {  
65 - updateParticipants(room)  
66 - }  
67 -  
68 override fun onActiveSpeakersChanged(speakers: List<Participant>, room: Room) { 57 override fun onActiveSpeakersChanged(speakers: List<Participant>, room: Room) {
69 } 58 }
70 59
71 - override fun onMetadataChanged(  
72 - room: Room,  
73 - Participant: Participant,  
74 - prevMetadata: String?  
75 - ) { 60 + override fun onMetadataChanged(Participant: Participant, prevMetadata: String?, room: Room) {
76 61
77 } 62 }
78 } 63 }
79 ) 64 )
  65 + updateParticipants(mutableRoom.value!!)
80 } 66 }
81 } 67 }
82 68
@@ -28,7 +28,7 @@ class ParticipantItem( @@ -28,7 +28,7 @@ class ParticipantItem(
28 viewBinding.run { 28 viewBinding.run {
29 29
30 remoteParticipant.listener = object : RemoteParticipant.Listener { 30 remoteParticipant.listener = object : RemoteParticipant.Listener {
31 - override fun onSubscribe( 31 + override fun onTrackSubscribed(
32 track: Track, 32 track: Track,
33 publication: TrackPublication, 33 publication: TrackPublication,
34 participant: RemoteParticipant 34 participant: RemoteParticipant